├── .github
└── FUNDING.yml
├── warp.swf
├── watch.swf
├── alt-swf
├── cpb.swf
├── cps.swf
├── mp.swf
├── 2006.swf
├── 2010.swf
├── 2012.swf
├── cps2.swf
├── e2006.swf
├── 2007ad.swf
├── modules
│ ├── 2010_endscreen-vfl183159.swf
│ ├── 2010_iv3_module-vfl183159.swf
│ ├── 2012_iv3_module-vfl7CyC10.swf
│ ├── 2010_subtitles3_module-vfl183159.swf
│ └── 2012_subtitles3_module-vflX-PxNh.swf
└── readme.md
├── doc-imgs
├── iv.png
├── ccmwc.png
├── ie6-ss.png
├── ie6-ss2.png
├── validiv.png
├── cc-mod-watch.png
├── defaultvalid.png
├── gdata-grep.png
├── grep-paths.png
├── pkcs5padding.png
├── signin-hppng.png
├── text-search.png
├── text-search2.png
├── validivvalid.png
├── flash-working.png
├── gdata-changed.png
├── registerDevice.png
├── script-export.png
├── signin-vidmngr.png
├── validurlsearch.png
├── 19216817captions.png
├── gdata-grep-marked.png
├── zerobytepadding.png
├── iv_descriptor_changed.png
├── iv_descriptor_initial.png
└── registerDevice-changed.png
├── iv_module.swf
├── xl
├── apiplayer.swf
├── apiplayer-f.swf
├── express-vfl124920.swf
├── express_bridge-vfl118365.swf
├── html5-embed
│ ├── player-imgs
│ │ ├── fw-btn.png
│ │ ├── hd-btn.png
│ │ ├── hq-btn.png
│ │ ├── loaded.png
│ │ ├── default.png
│ │ ├── loop-btn.png
│ │ ├── pause-btn.png
│ │ ├── play-btn.png
│ │ ├── sprites.png
│ │ ├── watched.png
│ │ ├── hd-btn-clck.png
│ │ ├── hq-btn-clck.png
│ │ ├── rewind-btn.png
│ │ ├── fullscreen-btn.png
│ │ ├── fw-btn-active.png
│ │ ├── hd-btn-active.png
│ │ ├── hq-btn-active.png
│ │ ├── pause-btn-active.png
│ │ ├── play-btn-active.png
│ │ ├── loop-btn-inactive.png
│ │ └── rewind-btn-active.png
│ └── index.html
├── xl-site-vfl84759.css
├── xl-base-vfl92884.css
└── yt2009.js
├── THANKS-OT.TXT
├── static_pages
├── cropped
│ ├── upload.html
│ ├── shows.html
│ ├── wariolandshakeit2008.html
│ ├── feather_beta.html
│ ├── new_viewing_experience.html
│ ├── warp_speed_en.html
│ ├── warp_speed.html
│ └── cbackground.html
└── header.html
├── subtitle-module.swf
├── leanback
├── leanback.swf
├── watch_as3-vfl183159.swf
└── index.html
├── player-imgs
├── replay.png
├── share.png
├── darker-bg.png
├── loaded-bg.png
├── loading.gif
├── main-bg.png
├── play-btn.png
├── seek_time.png
├── load-static.png
├── embed-bgs
│ ├── blue.png
│ ├── dark.png
│ ├── dred.png
│ ├── pink.png
│ ├── dblue.png
│ ├── green.png
│ ├── orange.png
│ ├── purple.png
│ └── user-gen
│ │ ├── fff.png
│ │ ├── ffff.png
│ │ ├── 000000.png
│ │ ├── 0000ff.png
│ │ ├── 00ff00.png
│ │ ├── 069420.png
│ │ ├── 222222.png
│ │ ├── 2f2f2f.png
│ │ ├── 368793.png
│ │ ├── 54abf6.png
│ │ ├── 694200.png
│ │ ├── febd11.png
│ │ ├── ff00ff.png
│ │ └── ffffff.png
├── play-btn-hover.png
├── play-btn-opt.png
├── player-buttons.png
├── player-tooltip.png
├── star-ratings.png
├── volume-popup.png
├── darker-bg-hover.png
├── endscreen-bg-opt.png
├── gradient_sprite.png
├── pause-annotation.png
├── seek-bar-main-bg.png
├── additions-buttons.png
├── captions-popup-base.png
├── fullscreen_frames.png
├── main-bg-translucent.png
├── pause-btn-flashing.png
├── play-btn-flashing.png
├── player_additions_bg.png
├── saber-pickr-sprites.png
├── seek-bar-elapsed-bg.png
├── endscreen-arrow-left.png
├── endscreen-arrow-right.png
├── fullscreen-exit-frames.png
├── player-buttons-transparent.png
├── player-additions-tooltip-inside.png
└── player-additions-tooltip-outside.png
├── docker-entrypoint.sh
├── mobile
├── mobilehelper
│ ├── s1.png
│ ├── s2.png
│ ├── s3.png
│ └── generic_default.xml
├── app_style.css
├── gdata_main_auth.html
├── blzr
│ ├── flags.js
│ └── flags.htm
├── playback_setup_basic.htm
├── playback_setup.htm
├── search.htm
└── view-comment.htm
├── assets
└── site-assets
│ ├── default.png
│ ├── empty.mp4
│ ├── success.png
│ ├── yt2007.png
│ ├── uploading.gif
│ ├── 8hldfhy63cw.jpg
│ ├── FEm8PZ_lUh8.jpg
│ ├── YZsMgrxGaMA.jpg
│ ├── _O7iUiftbKU.jpg
│ ├── embed-size.png
│ ├── embed-thumb.png
│ ├── gmvjvlOnBYw.jpg
│ ├── pDz4JG-QOJk.jpg
│ ├── rTjdXDkl9Uo.jpg
│ ├── success_mini.gif
│ ├── warp-hover.png
│ ├── autoshare-bsky.png
│ ├── partner
│ ├── demand.jpg
│ ├── boburnham.jpg
│ ├── davedays.jpg
│ ├── charlestrippy.jpg
│ ├── collegehumor.jpg
│ ├── communitychannel.jpg
│ └── partners-videos-vfl85500.png
│ ├── wwsi2008
│ ├── main.swf
│ ├── video_item_thumbs
│ │ ├── 1.jpg
│ │ ├── 2.jpg
│ │ ├── 3.jpg
│ │ ├── 4.jpg
│ │ ├── 5.jpg
│ │ └── 6.jpg
│ ├── videoPlayer
│ │ └── videoPlayerAS2.swf
│ ├── style.css
│ └── config.xml
│ ├── default-centered.png
│ ├── msg_icn-vfl138364.png
│ ├── world-chart-base.png
│ ├── adv-arrows-vfl85178.gif
│ ├── doodles
│ ├── logo_lunar.png
│ ├── logo-clownnose.png
│ ├── logo-superbowl.png
│ ├── logo_july4th.png
│ ├── logo_symphony.png
│ ├── logo_analog_off.gif
│ ├── logo_eurovision.png
│ ├── logo-custom-nov17.png
│ ├── logo-remade-stpats.png
│ ├── logo-valentinesday.png
│ ├── logo_halloween-vfl129017.png
│ ├── logo_solstice-vfl138400.png
│ ├── logo-world_environment_day.png
│ ├── symphony
│ │ ├── logo_symphony-nb.png
│ │ ├── logo_symphony-left.png
│ │ └── logo_symphony-vfl89746.png
│ ├── logo-german-election-vfl122998.png
│ ├── logo_holy_crap_1bn_a_day-vfl124472.png
│ └── ORIGINAL SOURCES.txt
│ ├── embed-size-selected.png
│ ├── warp-hover-overflow.png
│ ├── youtube_google_brand.gif
│ ├── player_tabs_bgnd-vfl82418.png
│ ├── player_tabs_downarrow-vfl82418.png
│ ├── flip.css
│ ├── html5-header.css
│ ├── load.html
│ ├── f.css
│ ├── arrow.svg
│ ├── yt2009videospreview.js
│ ├── fe.js
│ ├── search-suggestions.css
│ ├── invalid-session-help.txt
│ ├── apr1.css
│ ├── yt2009langpicker.js
│ ├── warp-stylesheet.css
│ ├── yt2009advsearch.js
│ ├── inbox_css.css
│ └── leanback_ajax.json
├── .gitattributes
├── crossdomain.xml
├── back
├── proto
│ ├── temp_behalfof.proto
│ ├── analytics_screen_request.proto
│ ├── android_search_request.proto
│ ├── create_comment.proto
│ ├── popularVidsChip.proto
│ ├── bare_android_request.proto
│ ├── watchNextFeed.proto
│ ├── android_next.proto
│ ├── android_resolve.proto
│ ├── cmts.proto
│ ├── README.txt
│ ├── sabr_response.proto
│ ├── newestFirstComments.proto
│ ├── android_user_metadata.proto
│ ├── android_guide.proto
│ ├── search_request_params.proto
│ ├── android_metadata_update.proto
│ ├── yt2009_channel.proto
│ ├── android_player_request.proto
│ ├── sabr.proto
│ └── android_search.proto
├── language_data
│ ├── h.json
│ └── language_engine.js
├── regenCaches.js
├── channel_backgrounds.json
├── cache_dir
│ ├── playlist_cache_manager.js
│ ├── backend_maintenance.js
│ ├── search_cache_manager.js
│ ├── video_cache_manager.js
│ ├── default_avatar_adapt_manager.js
│ ├── channel_cache.js
│ ├── rating_cache_manager.js
│ ├── video_exists_cache_mgr.js
│ ├── ryd_cache_manager.js
│ └── captions_cache_mgr.js
├── yt2009inbox.js
├── LICENSE-GOOGLEVIDEO
├── detect_default_avatar.js
├── yt2009quicklistserver.js
├── geo
│ └── continent-data.json
├── dominant_color.js
├── yt2009doodles.js
├── yt2009clientplaylists.js
├── yt2009static.js
├── backend_wrap.js
├── yt2009loginsimulate.js
└── yt2009mobileflags.js
├── auth_basic.html
├── package.json
├── warp.html
├── flags_main.htm
├── auth.html
├── t.htm
├── r.htm
├── strictifier.js
├── cbg_uploadr.html
├── Dockerfile
├── unauth.htm
├── config_params.md
├── windowsxp.md
├── convertify.js
└── .gitignore
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: ftde0
--------------------------------------------------------------------------------
/warp.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/warp.swf
--------------------------------------------------------------------------------
/watch.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/watch.swf
--------------------------------------------------------------------------------
/alt-swf/cpb.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/alt-swf/cpb.swf
--------------------------------------------------------------------------------
/alt-swf/cps.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/alt-swf/cps.swf
--------------------------------------------------------------------------------
/alt-swf/mp.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/alt-swf/mp.swf
--------------------------------------------------------------------------------
/doc-imgs/iv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/doc-imgs/iv.png
--------------------------------------------------------------------------------
/iv_module.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/iv_module.swf
--------------------------------------------------------------------------------
/alt-swf/2006.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/alt-swf/2006.swf
--------------------------------------------------------------------------------
/alt-swf/2010.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/alt-swf/2010.swf
--------------------------------------------------------------------------------
/alt-swf/2012.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/alt-swf/2012.swf
--------------------------------------------------------------------------------
/alt-swf/cps2.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/alt-swf/cps2.swf
--------------------------------------------------------------------------------
/alt-swf/e2006.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/alt-swf/e2006.swf
--------------------------------------------------------------------------------
/xl/apiplayer.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/xl/apiplayer.swf
--------------------------------------------------------------------------------
/THANKS-OT.TXT:
--------------------------------------------------------------------------------
1 | all one time sponsors -- thank you everyone!
2 |
3 | @CubeFun - 2025-10-24
--------------------------------------------------------------------------------
/alt-swf/2007ad.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/alt-swf/2007ad.swf
--------------------------------------------------------------------------------
/doc-imgs/ccmwc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/doc-imgs/ccmwc.png
--------------------------------------------------------------------------------
/doc-imgs/ie6-ss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/doc-imgs/ie6-ss.png
--------------------------------------------------------------------------------
/doc-imgs/ie6-ss2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/doc-imgs/ie6-ss2.png
--------------------------------------------------------------------------------
/doc-imgs/validiv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ftde0/yt2009/HEAD/doc-imgs/validiv.png
--------------------------------------------------------------------------------
/static_pages/cropped/upload.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/cbg_uploadr.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
24 |
25 |
29 |
56 |
57 |
--------------------------------------------------------------------------------
/mobile/blzr/flags.js:
--------------------------------------------------------------------------------
1 | function $(element) {
2 | if(document.querySelectorAll(element).length !== 1) {
3 | return document.querySelectorAll(element);
4 | } else {
5 | return document.querySelector(element)
6 | }
7 | }
8 |
9 | // send flags
10 | function saveFlags() {
11 | var watchFlags = ""
12 | var searchFlags = ""
13 | var login_simulate = ""
14 |
15 | var inputs = document.getElementsByTagName("input")
16 | for(var i in inputs) {
17 | if(inputs[i].tagName
18 | && inputs[i].type == "checkbox"
19 | && inputs[i].checked) {
20 | switch(inputs[i].id.split("-")[0]) {
21 | case "watch": {
22 | watchFlags += inputs[i].id.replace("watch-", "")
23 | if(document.getElementById(inputs[i].id + "-box")) {
24 | var textbox = document.getElementById(inputs[i].id + "-box")
25 | searchFlags += textbox.value
26 | }
27 |
28 | watchFlags += ":"
29 | break;
30 | }
31 | case "search": {
32 | searchFlags += inputs[i].id.replace("search-", "")
33 | if(document.getElementById(inputs[i].id + "-box")) {
34 | var textbox = document.getElementById(inputs[i].id + "-box")
35 | searchFlags += textbox.value
36 | }
37 |
38 | searchFlags += ":"
39 | break;
40 | }
41 | case "ls": {
42 | login_simulate = document.getElementById(inputs[i].id + "-box").value
43 | break;
44 | }
45 | }
46 | }
47 | }
48 |
49 | document.cookie = "blzr_watch_flags=" + watchFlags + "; Path=/; expires=Fri, 31 Dec 2066 23:59:59 GMT"
50 | document.cookie = "blzr_search_flags=" + searchFlags + "; Path=/; expires=Fri, 31 Dec 2066 23:59:59 GMT"
51 | document.cookie = "blazer_login=" + login_simulate + "; Path=/; expires=Fri, 31 Dec 2066 23:59:59 GMT"
52 |
53 | alert("ok")
54 | }
--------------------------------------------------------------------------------
/assets/site-assets/yt2009langpicker.js:
--------------------------------------------------------------------------------
1 | var yt = {
2 | "www": {
3 | "masthead": {
4 | "loadPicker": yt2009_loadPicker
5 | }
6 | }
7 | }
8 |
9 | function loadPicker(arg) {
10 | yt2009_loadPicker(arg)
11 | }
12 |
13 | function yt2009_loadPicker(arg) {
14 | if(arg == "language-picker") {
15 | var picker = document.getElementById("language-picker-container")
16 | var r;
17 | if (window.XMLHttpRequest) {
18 | r = new XMLHttpRequest()
19 | } else {
20 | r = new ActiveXObject("Microsoft.XMLHTTP");
21 | }
22 | r.open("GET", "/language_picker")
23 | r.send(null)
24 | r.onreadystatechange = function(e) {
25 | if(r.readyState == 4
26 | || this.readyState == 4
27 | || e.readyState == 4) {
28 | picker.innerHTML = r.responseText
29 | }
30 | }
31 | } else if(arg == "region-picker") {
32 | var picker = document.getElementById("region-picker-container")
33 | var r;
34 | if (window.XMLHttpRequest) {
35 | r = new XMLHttpRequest()
36 | } else {
37 | r = new ActiveXObject("Microsoft.XMLHTTP");
38 | }
39 | r.open("GET", "/region_picker")
40 | r.send(null)
41 | r.onreadystatechange = function(e) {
42 | if(r.readyState == 4
43 | || this.readyState == 4
44 | || e.readyState == 4) {
45 | picker.innerHTML = r.responseText
46 | }
47 | }
48 | }
49 | return false;
50 | }
51 |
52 | function setLang(lang) {
53 | document.cookie = "lang=" + lang
54 | + "; Path=/; expires=Fri, 31 Dec 2066 23:59:59 GMT"
55 | location.reload()
56 | }
57 |
58 | function setLoc(loc) {
59 | document.cookie = "gl=" + loc
60 | + "; Path=/; expires=Fri, 31 Dec 2066 23:59:59 GMT"
61 | location.reload()
62 | }
63 |
64 | function closeLangPicker() {
65 | document.getElementById("language-picker-container").innerHTML = ""
66 | }
67 |
68 | function closeLocPicker() {
69 | document.getElementById("region-picker-container").innerHTML = ""
70 | }
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:lts-alpine3.20
2 | RUN apk add --no-cache imagemagick cabextract && \
3 | wget -P /tmp/ https://www.freedesktop.org/software/fontconfig/webfonts/webfonts.tar.gz && \
4 | tar -xzf /tmp/webfonts.tar.gz -C /tmp && \
5 | cabextract /tmp/msfonts/arial32.exe -d /tmp && \
6 | apk del cabextract && \
7 | install -D -t /usr/share/fonts /tmp/Arial.TTF && \
8 | rm -rf /tmp/* && \
9 | fc-cache -f && \
10 | mkdir /data && \
11 | chown node /data
12 |
13 | COPY --from=mwader/static-ffmpeg:7.0.2 /ffmpeg /usr/local/bin/
14 |
15 | ADD --chown=node . /yt2009
16 | WORKDIR /yt2009
17 | USER node
18 |
19 | # PLEASE READ THIS IT WILL SAVE YOU MUCH HASSLE
20 | # don't modify the environment variables here if you're hosting, those are the defaults and are not supposed to be changed unless you're a developer
21 | # you can instead set them when launching the container, this way you don't have to fork the repo or rebuild the container every time you want to change something
22 | # if someone has told you to do modify them here please ignore their advice and tell them they're wrong
23 | ENV YT2009_PORT=80 \
24 | YT2009_ENV=dev \
25 | YT2009_IP=127.0.0.1 \
26 | YT2009_SSL=false \
27 | YT2009_SSLPORT=443 \
28 | YT2009_SSLPATH=/yt2009/cert.crt \
29 | YT2009_SSLKEY=/yt2009/cert.key \
30 | YT2009_AUTO_MAINTAIN=false \
31 | YT2009_MAINTAIN_MAX_SIZE=10 \
32 | YT2009_MAINTAIN_MAX_CACHE_SIZE=15 \
33 | YT2009_FALLBACK=false \
34 | YT2009_DISABLEMASTER=false \
35 | YT2009_RATELIMIT=false \
36 | YT2009_AC=false \
37 | YT2009_GDATA_AUTH=false
38 |
39 | RUN npm install && \
40 | ln -s /data/androiddata.json back/androiddata.json && \
41 | ln -s /data/tvdata.json back/tvdata.json && \
42 | ln -s /data/config.json back/config.json && \
43 | ln -s /data/mobilehelper_userdata.json back/mobilehelper_userdata.json && \
44 | ln -s /data/comments.json back/cache_dir/comments.json && \
45 | ln -s /data/accessdata back/accessdata && \
46 | ln -s /data/cert.crt cert.crt && \
47 | ln -s /data/cert.key cert.key && \
48 | echo "{\"env\": \"dev\"}" > back/config.json && \
49 | node post_config_setup.js
50 |
51 | CMD ["node", "backend.js"]
52 | ENTRYPOINT ["sh", "docker-entrypoint.sh"]
53 |
--------------------------------------------------------------------------------
/back/yt2009doodles.js:
--------------------------------------------------------------------------------
1 | /*
2 | yt2009 doodles
3 |
4 | property names inside of doodles variable are mm-dd!!
5 | */
6 | const doodles = {
7 | "2-1": "/assets/site-assets/doodles/logo-superbowl.png",
8 | "2-14": "/assets/site-assets/doodles/logo-valentinesday.png",
9 | "3-13": "/assets/site-assets/doodles/logo-clownnose.png",
10 | "3-17": "/assets/site-assets/doodles/logo-remade-stpats.png",
11 | "4-15": "/assets/site-assets/doodles/logo_symphony.png",
12 | "5-16": "/assets/site-assets/doodles/logo_eurovision.png",
13 | "6-12": "/assets/site-assets/doodles/logo_analog_off.gif",
14 | "7-4": "/assets/site-assets/doodles/logo_july4th.png",
15 | "7-20": "/assets/site-assets/doodles/logo_lunar.png",
16 | "10-9": "/assets/site-assets/doodles/logo_holy_crap_1bn_a_day-vfl124472.png",
17 | "10-12": "/assets/site-assets/doodles/logo-german-election-vfl122998.png",
18 | "10-31": "/assets/site-assets/doodles/logo_halloween-vfl129017.png",
19 | "11-17": "/assets/site-assets/doodles/logo-custom-nov17.png",
20 | "christmas": "/assets/site-assets/doodles/logo_solstice-vfl138400.png"
21 | }
22 |
23 | const replacableCodes = [
24 | `
`,
25 | `
`,
26 | `
`,
27 | ]
28 |
29 | module.exports = {
30 | "getDoodle": function() {
31 | let d = new Date()
32 | let date = (d.getMonth() + 1) + "-" + d.getDate()
33 | if(d.getMonth() == 11 && (d.getDate() >= 21 && d.getDate() <= 25)) {
34 | date = "christmas"
35 | }
36 |
37 | return doodles[date] || false;
38 | },
39 |
40 | "applyDoodle": function(code, req) {
41 | if(this.getDoodle()
42 | && (!req || !req.headers || !req.headers.cookie
43 | || !req.headers.cookie.includes("no_doodles"))) {
44 | let d = this.getDoodle()
45 | let dc = `
`
46 | replacableCodes.forEach(c => {
47 | code = code.replace(c, dc)
48 | })
49 | }
50 |
51 | return code;
52 |
53 | }
54 | }
--------------------------------------------------------------------------------
/back/yt2009clientplaylists.js:
--------------------------------------------------------------------------------
1 | /*
2 | =======
3 | /my_playlists handler
4 | =======
5 |
6 | yt2009, 2022-2034
7 | */
8 |
9 | const utils = require("./yt2009utils")
10 | const template = require("./yt2009templates")
11 | const fs = require("fs")
12 | const page = fs.readFileSync("../playlists.htm").toString()
13 | const doodles = require("./yt2009doodles")
14 | const languages = require("./language_data/language_engine")
15 |
16 | module.exports = {
17 | "apply": function(req, res) {
18 | if(!utils.isAuthorized(req)) {
19 | res.send("")
20 | return;
21 | }
22 | req = utils.addFakeCookie(req)
23 |
24 | let code = page;
25 |
26 | // shows tab
27 | if(req.headers.cookie.includes("shows_tab")) {
28 | code = code.replace(
29 | `
lang_channels `,
30 | `
lang_channels lang_shows `
31 | )
32 | }
33 |
34 | // render cookie playlists (f_mode)
35 | if(req.headers.cookie.includes("playlist_index")) {
36 | let playlistIndexHTML = ``
37 | let playlistIndex = req.headers.cookie.split("playlist_index=")[1]
38 | .split(";")[0]
39 | playlistIndex.split(":").forEach(playlist => {
40 | if(!playlist) return;
41 | playlist = decodeURIComponent(playlist)
42 | playlistIndexHTML += template.playlist(
43 | playlist.split(";")[0],
44 | playlist.split(";")[1]
45 | )
46 | })
47 |
48 | code = code.replace(``, playlistIndexHTML)
49 | }
50 |
51 | if(req.headers.cookie.includes("f_mode=on")) {
52 | code = code.replace(
53 | ``,
54 | ``
55 | )
56 | }
57 |
58 | code = require("./yt2009loginsimulate")(req, code, true);
59 | code = doodles.applyDoodle(code, req)
60 | code = languages.apply_lang_to_code(code, req)
61 | res.send(code);
62 | }
63 | }
--------------------------------------------------------------------------------
/unauth.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | yt2009_utils
8 |
9 |
10 |
11 |
12 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
42 |
43 |
44 |
45 |
unauthorized
46 |
what happened?
47 |
no authorization cookie was passed with your request.
48 | the authorization cookie that's normally sent includes your access token you enter on /auth.html .
49 | however, no such cookie was there.
50 |
what could have caused this?
51 |
52 | browser caching
53 | removing/disabling browser cookies
54 | no authorization key set.
55 |
56 |
how to fix?
57 |
58 | set your access token using /auth.html .
59 | try clearing your browser cache.
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/alt-swf/readme.md:
--------------------------------------------------------------------------------
1 | # alt-swf
2 |
3 | alt-swf is a directory where alternative flash player SWFs are stored for /toggle_f on yt2009.
4 |
5 | included SWFs are prepatched for use with yt2009. their original file names and links are provided below.
6 |
7 | modules found under `/modules/` have their original file names, just with the player year they're intended to be used with in the beginning of the file name.
8 |
9 | |swf filename|link|description|
10 | |--------|--|--|
11 | |2006.swf|[player2.swf](https://web.archive.org/web/20070116122143oe_/youtube.com/player2.swf)|a standard late-2006-2007 video player.
12 | |2007ad.swf|[admp.swf](https://web.archive.org/web/20070219063115oe_/youtube.com/admp.swf)|the flash player used in homepage video ads in 2007.
13 | |2010.swf|[watch_as3-vfl5PVWS5.swf](http://web.archive.org/web/20100910001617oe_/http://s.ytimg.com//yt//swf//watch_as3-vfl5PVWS5.swf)|the standard late-2010 video player
14 | |2012.swf|[watch_as3-vflJogbdx.swf](http://web.archive.org/web/20120705001433oe_/https://s.ytimg.com/yt/swfbin/watch_as3-vflJogbdx.swf)|the standard 2012 video player
15 | |e2006.swf|[player2.swf](http://web.archive.org/web/20060706195428oe_/http://youtube.com:80/player2.swf)|an early-mid 2006 player.
16 | |cpb.swf|[cpb-vflzG1o7y.swf](http://web.archive.org/web/20101222144444oe_/s.ytimg.com/yt/swfbin/cpb-vflzG1o7y.swf)|embedded playlist player linked by the playlist view page. (when patching, also change the gdata base url!!)
17 | |cps.swf|[cps-vfl_gIfdw.swf](http://web.archive.org/web/20120427131527oe_/http://s.ytimg.com/yt/swfbin/cps-vfl_gIfdw.swf)|player with built-in search. used as a fallback in some years. (also change gdata base url!)
18 | |mp.swf|[mp-vfl146722.swf](web.archive.org/web/20100327054256oe_/http://s.ytimg.com/yt/m/mobile/swf/mp-vfl146722.swf)|mobile player for flash enabled phones
19 | ---
20 | ## bonus: find your own!
21 |
22 | if you have way too much time, feel free to look through the Wayback Machine and find some interesting players!
23 |
24 | here are some resources to help you do so:
25 |
26 | - [s.ytimg.com/yt/swf/ files (2007-late2010)](https://web.archive.org/web/*/http://s.ytimg.com/yt/swf/*)
27 | - [s.ytimg.com/yt/swfbin/ files](https://web.archive.org/web/*/http://s.ytimg.com/yt/swfbin/*)
28 | - when looking through pages like /watch on Wayback Machine, view the page source to get its .swf file links
--------------------------------------------------------------------------------
/back/proto/yt2009_channel.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package yt2009_channel_customizations;
3 |
4 | message featuredChannel {
5 | string id = 1;
6 | string name = 2;
7 | string pictureUrl = 3; /*unused*/
8 | }
9 |
10 | message root {
11 | string title = 1;
12 | string type = 2;
13 | /* ^^^
14 | u = YouTuber
15 | d = Director
16 | m = Musician
17 | c = Comedian
18 | g = Guru
19 | j = Reporter*/
20 | string tags = 3;
21 | optional int32 themeId = 4;
22 | /* ^^^
23 | 1 - Grey
24 | 2 - Blue
25 | 3 - Red
26 | 4 - Sunlight
27 | 5 - Forest
28 | 6 - 8-bit
29 | 7 - Princess
30 | 8 - Fire
31 | 9 - Stealth
32 | 10 - Clean
33 | 11 - custom
34 | */
35 | optional int32 font = 5;
36 | /* ^^^
37 | 1 - Times New Roman // serif
38 | 2 - Arial
39 | 3 - Verdana
40 | 4 - Georgia
41 | 5 - Courier New
42 | */
43 |
44 | /*all color values in hex, without the leading #*/
45 | /*opacity values 0-255*/
46 | string backgroundColor = 6;
47 | string wrapperColor = 7;
48 | string wrapperTextColor = 8;
49 | string wrapperLinkColor = 9;
50 | optional int32 wrapperOpacity = 10;
51 | string customBackgroundId = 11;
52 | bool repeatCustomBackground = 12;
53 |
54 | string innerboxBackgroundColor = 13;
55 | string innerboxTitleTextColor = 14;
56 | string innerboxLinkColor = 15;
57 | string innerboxBodyTextColor = 16;
58 | optional int32 innerboxOpacity = 17;
59 |
60 | string shownModules = 18;
61 | /*shownModules = single characters indicating what modules should be shown
62 |
63 | c = comments
64 | r = recent activity
65 | s = subscribers
66 | z = subscriptions
67 | o = other channels
68 |
69 | s and z are partially exposed into 19 and 20 once allowed*/
70 | repeated featuredChannel subscriber = 19;
71 | repeated featuredChannel subscription = 20;
72 |
73 | string shownContent = 21;
74 | /*shownContent - single characters:
75 |
76 | u = uploaded
77 | f = favorites
78 | p = playlists
79 | a = "all"*/
80 |
81 | bool defaultGrid = 22;
82 | int32 altDefaultSet = 23;
83 | /* ^^^
84 | 2 - uploaded
85 | 3 - favorites*/
86 |
87 | string altDefaultVidId = 24;
88 |
89 | bool hideBanner = 25;
90 |
91 | bool enableAutoplay = 26;
92 | }
--------------------------------------------------------------------------------
/mobile/playback_setup_basic.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
yt2009 mobile playback setup
7 |
8 |
9 |
10 |
playback setup
11 |
set how videos should be played on mobile.
12 | select the appropriate option and save.
13 |
38 |
39 |
--------------------------------------------------------------------------------
/assets/site-assets/warp-stylesheet.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: black;
3 | overflow: hidden;
4 | cursor: pointer;
5 | color: white;
6 | user-select: none;
7 | }
8 |
9 | * {
10 | margin: 0px 0px;
11 | }
12 |
13 | .container {
14 | position: absolute;
15 | left: 0px;
16 | top: 0px;
17 | width: 100%;
18 | height: 100%;
19 | }
20 |
21 | .warp_grid {
22 | position: absolute;
23 | width: 5000px;
24 | height: 5000px;
25 | border: 1px white solid;
26 | }
27 |
28 | .video-circle {
29 | position: absolute;
30 | border: 10px white solid;
31 | border-radius: 64px;
32 | width: 64px;
33 | height: 64px;
34 | background-size: cover;
35 | -moz-background-size: cover;
36 | border-radius: 50px;
37 | -moz-border-radius: 64px;
38 | -webkit-transition: all 1s;
39 | -moz-transition: all 1s;
40 | transition: all 1s;
41 | background-position: center;
42 | }
43 |
44 | .video-circle.small {
45 | width: 50px;
46 | height: 50px;
47 | }
48 |
49 | .overlay {
50 | display: table;
51 | position: absolute;
52 | left: 0px;
53 | top: 0px;
54 | width: 100%;
55 | height: 100%;
56 | background: rgba(0, 0, 0, 0.6);
57 | text-align: center;
58 | }
59 |
60 | .inner {
61 | display: table-cell;
62 | vertical-align: middle;
63 | }
64 |
65 | .overlay .center {
66 | margin: auto auto;
67 | }
68 |
69 | .player-embed {
70 | width: 960px;
71 | height: 540px;
72 | }
73 |
74 | /*
75 | informacje o filmie
76 | */
77 |
78 | .hover-element {
79 | position: absolute;
80 | left: 0px;
81 | top: 0px;
82 | color: black;
83 | width: 245px;
84 | height: 73px;
85 | background-image: url("/assets/site-assets/warp-hover.png"), url("/assets/site-assets/warp-hover-overflow.png");
86 | background-repeat: no-repeat, repeat-x;
87 | white-space: nowrap;
88 | }
89 |
90 | .video-title {
91 | position: absolute;
92 | left: 77px;
93 | top: 6px;
94 | font-size: 12px;
95 | font-family: Arial, sans-serif;
96 | }
97 |
98 | .length {
99 | position: absolute;
100 | left: 79px;
101 | top: 37px;
102 | font-size: 10px;
103 | font-family: Arial, sans-serif;
104 | }
105 |
106 | .thumbnail {
107 | position: absolute;
108 | left: 5px;
109 | top: 5px;
110 | width: 66px;
111 | height: 44px;
112 | }
--------------------------------------------------------------------------------
/mobile/playback_setup.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
yt2009 mobile playback setup
7 |
8 |
9 |
10 |
setting without JS?
11 |
playback setup
12 |
set how videos should be played on mobile.
13 | click the correct option and your option will be saved automatically.
14 |
RTSP / H264 MP4
15 |
RTSP / H264 MP4 (no audio)
16 |
RTSP / 3GP
17 |
RTSP / 3GP (no audio)
18 |
HTTP / H264 MP4
19 |
HTTP / H264 MP4 / 144P
20 |
HTTP / 3GP
21 |
HTTP / LQ/WMV
22 |
HTTP / XVID
23 |
HTTP / FLASH / FLV
24 |
HTTP / FLASH / H264 MP4
25 |
bonus: toggle old_experience: exp_related and only_old together.
26 |
old_experience
27 |
47 |
48 |
--------------------------------------------------------------------------------
/back/proto/android_player_request.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package android_player_request;
3 |
4 | /*android /player REQUEST to send to yt*/
5 |
6 | message hwData {
7 | fixed32 id = 12;
8 | }
9 |
10 | message appConfig {
11 | string coldConfigData = 1;
12 | string coldHashData = 3;
13 | string hotHashData = 5;
14 | }
15 |
16 | message adSignalsMsg {
17 | repeated uint64 signal = 4;
18 | }
19 |
20 | message playbackContextMsg {
21 | message contentContext {
22 | int32 one = 1;
23 | int32 two = 2;
24 | string highRec = 6;
25 | string sourceFeed = 11;
26 | }
27 | repeated contentContext contentPlaybackContext = 1;
28 | }
29 |
30 | message root {
31 | message contextType {
32 | message clientType {
33 | string deviceMake = 12;
34 | string deviceModel = 13;
35 | int32 clientNumber = 16;
36 | string clientVersion = 17;
37 | string osName = 18;
38 | string osVersion = 19;
39 | repeated hwData hw = 21;
40 | string gl = 22;
41 | string plreq = 25;
42 | int32 screenWidth = 37;
43 | int32 screenHeight = 38;
44 | int32 screenWidth2 = 55;
45 | int32 screenHeight2 = 56;
46 | repeated appConfig configInfo = 62;
47 | optional int32 utcOffsetMinutes = 67;
48 | string timeZone = 80;
49 | repeated adSignalsMsg adSignals = 84;
50 | string deviceCodename = 92;
51 | }
52 | repeated clientType client = 1;
53 | /*message clickTrackingParamsMsg {
54 | message contents {
55 |
56 | }
57 | repeated contents content = 2;
58 | }
59 | repeated clickTrackingParamsMsg clickTrackingParams = 6;*/
60 | }
61 | repeated contextType context = 1;
62 | string videoId = 2;
63 | optional int32 racyCheckOk = 3;
64 | repeated playbackContextMsg playbackContext = 4;
65 | optional int32 contentCheckOk = 5;
66 | string pps = 12;
67 | message serviceIntegrityDimensionsMsg {
68 | message contents {
69 | optional bytes encryptData = 1;
70 | optional bytes tokenData = 2;
71 | }
72 | repeated contents content = 1;
73 | }
74 | repeated serviceIntegrityDimensionsMsg serviceIntegrityDimensions = 27;
75 | message otherVariousSets {
76 | optional int32 dataSaving = 1;
77 | int32 two = 2;
78 | int64 initTimeMs = 3;
79 | }
80 | repeated otherVariousSets sets = 28;
81 | }
--------------------------------------------------------------------------------
/static_pages/cropped/new_viewing_experience.html:
--------------------------------------------------------------------------------
1 |
17 |
18 |
Your New Viewing Experience
19 |
At YouTube, we're always looking to improve the way you watch videos online. As part of that, today we're excited to introduce our new page layout. Here are some tips for getting the most out of your new YouTube viewing experience:
20 |
21 |
22 |
23 | 1
24 |
25 |
26 |
Turn your monitor upside-down
27 |
Our internal tests have shown that modern computer monitors give a higher quality picture when flipped upside down—kind of like how it's best to rotate your mattress every six months. You might find that YouTube videos look better this way.
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | 2
36 |
37 |
38 |
Tilt your head to the side
39 |
Imagine you've got water in your ear and need to get it out. Tilt your head toward one shoulder and watch the video (gentle head-smacking on the opposite side is optional).
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | 3
48 |
49 |
50 |
Move to Australia
51 |
As you probably know, everything in Australia is upside-down, so moving to Australia may provide you with a more natural YouTube viewing experience. (Note: If you live Down Under, and the page is still upside-down for you, then we recommended moving to the northern hemisphere.)
52 |
53 |
54 |
55 |
56 |
57 |
58 |
Of course, if you prefer the way things used to be, just click on the "I prefer the old-fashioned layout!" when watching a video.
59 |
Happy April 1st!
60 |
--------------------------------------------------------------------------------
/static_pages/cropped/warp_speed_en.html:
--------------------------------------------------------------------------------
1 |
[pl]
2 |
3 |
warp:
4 |
paste a video link here to generate a warp link - youtube browser removed in 2011. more info: click here select a version:
5 |
6 |
7 |
html+js+css recreation
8 |
9 |
original flash version fixed to work with yt2009
10 |
11 |
12 | use h264 with flash
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/static_pages/cropped/warp_speed.html:
--------------------------------------------------------------------------------
1 |
[en]
2 |
3 |
warp:
4 |
wklej tu link do filmu, aby wygenerować link warp - wizualnej przeglądarki yt usuniętej w 2011. więcej informacji: kliknij tu. wybierz wersję:
5 |
6 |
7 |
rekreacja html+js+css
8 |
9 |
oryginalna wersja flash, naprawiona aby działała z yt2009
10 |
11 |
12 | używaj h264 z flash
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/static_pages/cropped/cbackground.html:
--------------------------------------------------------------------------------
1 |
13 |
yt2009: suggest better channel background
14 |
15 |
Get channel
16 |
17 |
below you will see old backgrounds of the linked user. if you see a fitting one, press "suggest".
18 | suggestions will be manually reviewed and if matching will be put in a list to use within the frontend.
19 | thank you!
20 |
image id: 101
21 |
previous
22 |
next
23 |
suggest
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/config_params.md:
--------------------------------------------------------------------------------
1 | # config.json
2 |
3 | as part of the setup process, yt2009 will write a file called `config.json` inside the `back` directory.
4 |
5 | inside you will find the properties you have set up using yt2009setup.js:
6 |
7 | - `port` - the port HTTP yt2009 will use
8 | - `env` - the environment (dev/prod)
9 | - `useSSL` - whether SSL (https) is used
10 | - `SSLCertPath` - SSL cert
11 | - `SSLKeyPath` - SSL private key
12 | - `SSLPort` - the port HTTP**s** yt2009 will use
13 | - `ip` - the IP address used for paths that need to have it hardcoded (e.g. gdata endpoints)
14 | - `auto_maintain` - automatically maintains space used by yt2009. toggle false: `true/false`.
15 | - `maintain_max_size` - max size of the /assets/ folder - number in GB. to be set with `auto_maintain`.
16 | - `maintain_max_cache_size` - max size per cache file - number in MB. to be set with `auto_maintain`.
17 |
18 | other params you can set:
19 |
20 | - `tokens` - an array of access tokens required to access if prod is used
21 | - `fallbackMode` - doesn't use the saved cache, shows a fallback notice on homepage. deprecated
22 | - `overrideMaster` - use a different master server for comments/video sync
23 | - `disableWs` - disable the use of a master server altogether
24 | - `templocked_tokens` - an array of access tokens that will be redirected to /t.htm
25 | - `customHomepageText` - a custom text that will be shown on the homepage
26 | - `redirmode` - an **absolute** http path of a different yt2009 instance you wish to redirect to
27 | - `logged_tokens` - an array of access tokens that will have their usage logged in `accessdata`.
28 | - `ratelimit` - a number of web fetch requests one ipv4 address/one ipv6 block can make in 1 minute.
29 | - `gdata_auth` - require token-based authorization for gdata api (e.g. mobile apps). `true/false`
30 | - `reencode_devs` - a list of user agent parts to reencode mp4s to a more compatible codec. comma-separated.
31 | - `trusted_context` - require additional "context" data to start download of mp4 videos. `true/false`
32 | - `tc_override_key` - a key for mp4 requests to bypass trusted context. more in yt2009trustedcontext.js.
33 | - `data_api_key` - accepts a google data api v3 for proper categories to show in video descriptions.
34 | - `file_limit` - a number in MB of max upload size. (default: 10)
35 | - `default_f` - should flash mode be enabled by default for new sessions. `true/false`
36 | - `default_fh264` - should H264 be enabled with flash by default for new sessions. `true/false`
37 | - `dl_max_retry` - maximum number of network retries for a download url. (default: 5)
38 | - `max_1080` - prevent from showing higher qualities than 1080p through html5. `true/false`
39 | - `ipv6` - a string containing your ipv6 subnet you can use. (e.g. "2a01:4f8:xxxx:xxxx")
--------------------------------------------------------------------------------
/back/yt2009static.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs")
2 | const header = fs.readFileSync("../static_pages/header.html")
3 | const footer = fs.readFileSync("../static_pages/footer.html")
4 | const utils = require("./yt2009utils")
5 | const templates = require("./yt2009templates")
6 | const doodles = require("./yt2009doodles")
7 | const languages = require("./language_data/language_engine")
8 |
9 | module.exports = {
10 | "createSite": function(path_to_content, req, res) {
11 | if(!utils.isAuthorized(req)) {
12 | res.send("")
13 | return;
14 | }
15 | req = utils.addFakeCookie(req)
16 | const content = fs.readFileSync("../static_pages/cropped/" + path_to_content)
17 | let site = header + content + footer
18 |
19 | if(req.headers.cookie.includes("shows_tab")) {
20 | // shows tab
21 | site = site.replace(
22 | `
Channels `,
23 | `
Channels Shows `
24 | )
25 | }
26 |
27 | if(utils.isUnsupportedNode()
28 | && site.includes(`var usesUnsupportedNode = false;`)) {
29 | site = site.replace(
30 | `var usesUnsupportedNode = false;`,
31 | `var usesUnsupportedNode = true;`
32 | )
33 | }
34 |
35 | const config = require("./config.json")
36 | site = site.split(
37 | `yt2009_http_root_url`
38 | ).join(`http://${config.ip}:${config.port}/`)
39 |
40 | // experimental: wordlist-based search suggestions
41 | // create the list in /wordlist.txt and separate suggestions
42 | // by newlines to use.
43 | if(fs.existsSync("../wordlist.txt")) {
44 | site = site.replace(
45 | ``,
46 | ``
47 | )
48 | site = site.replace(
49 | ``,
50 | `
`
51 | )
52 | }
53 |
54 | if(req.query.f == 1 || req.headers.cookie.includes("f_mode")) {
55 | site = site.replace(``, templates.html4)
56 | } else {
57 | site = site.replace(
58 | ``,
59 | `
`
60 | )
61 | site = site.replace(`yt2009_html5_mark`, `html5`)
62 | }
63 | site = require("./yt2009loginsimulate")(req, site)
64 | site = doodles.applyDoodle(site, req)
65 | site = languages.apply_lang_to_code(site, req)
66 | res.send(site)
67 | }
68 | }
--------------------------------------------------------------------------------
/xl/yt2009.js:
--------------------------------------------------------------------------------
1 | // html5 support
2 | var use_html5 = false;
3 | var current_video = "";
4 | if(location.href.indexOf("html5=1") !== -1) {
5 | use_html5 = true;
6 | }
7 |
8 | var video_change_event;
9 | // patch in the html5 iframe
10 | var old_id = "";
11 | video_change_event = setInterval(function() {
12 | if(current_video !== old_id
13 | && use_html5) {
14 | setTimeout(function() {
15 | var html5_video = document.createElement("iframe")
16 | html5_video.src = "/xl/embed?video_id=" + current_video;
17 | html5_video.allowFullscreen = true;
18 | html5_video.className = "yt2009-full"
19 | document.querySelector(".xl-view-player-video").innerHTML = ""
20 | document.querySelector(".xl-view-player-video").appendChild(html5_video)
21 | }, 250)
22 | }
23 | old_id = current_video;
24 |
25 | // write to last 3 vids
26 | var history = ""
27 | if(document.cookie
28 | && document.cookie.indexOf("xl_history=") !== -1) {
29 | history = document.cookie.split("xl_history=")[1].split(";")[0]
30 | history = history.split(":").slice(0, 2).join(":")
31 | }
32 | if(current_video == "") return;
33 | if(history.indexOf(current_video) !== -1) return;
34 | history = current_video + ":" + history
35 | document.cookie = "xl_history=" + history + "; Path=/xl; expires=Fri, 31 Dec 2066 23:59:59 GMT";
36 | }, 500)
37 |
38 | // check if flash loaded, throw a message otherwise
39 | function checkFlash() {
40 | if(document.getElementsByTagName("object").length <= 0
41 | && document.getElementsByTagName("embed").length <= 0
42 | && !use_html5) {
43 | document.getElementById("main.player.video").innerHTML += "\
44 |
your browser may not support flash. load html5 "
45 |
46 | setTimeout(function() {
47 | document.getElementById("main.player.video")
48 | .getElementsByTagName("button")[0]
49 | .onclick = function() {
50 | location.href += "?html5=1"
51 | }
52 | }, 150)
53 | }
54 | }
55 |
56 | // wayback_features warning
57 | if(document.cookie
58 | && document.cookie.indexOf("watch_flags=") !== -1
59 | && document.cookie.indexOf("xl_wayback_warning") == -1) {
60 | var watchFlags = document.cookie
61 | .split("watch_flags=")[1]
62 | .split(";")[0];
63 | if(watchFlags.indexOf("wayback_features") !== -1) {
64 | alert("\
65 | you seem to have the wayback_features watchpage flag enabled.\
66 | while xl will work, related videos will be retrieved from that source instead, which will be slow.")
67 | document.cookie = "xl_wayback_warning=1; Path=/; expires=Fri, 31 Dec 2066 23:59:59 GMT";
68 | }
69 | }
--------------------------------------------------------------------------------
/back/language_data/language_engine.js:
--------------------------------------------------------------------------------
1 | const langs = {
2 | "en": require("./en.json"),
3 | "pl": require("./pl.json"),
4 | "h": require("./h.json"),
5 | "sr-RS": require("./sr-RS.json"),
6 | "sr-Latn-RS": require("./sr-Latn-RS.json"),
7 | "ja-jp": require("./ja-jp.json"),
8 | "ru": require("./ru.json"),
9 | "de": require("./de.json"),
10 | "tr": require("./tr.json")
11 | }
12 | const displayNames = {
13 | "US": "Worldwide",
14 | "DE": "Germany",
15 | "NZ": "New Zealand",
16 | "CA": "Canada",
17 | "UK": "UK",
18 | "IE": "Ireland",
19 | "AU": "Australia",
20 | "ES": "Spain",
21 | "MX": "Mexico",
22 | "FR": "France",
23 | "IT": "Italy",
24 | "JP": "Japan",
25 | "NL": "Netherlands",
26 | "PL": "Poland",
27 | "BR": "Brazil",
28 | "RU": "Russia",
29 | "HK": "Hong Kong",
30 | "TW": "Taiwan",
31 | "KR": "South Korea",
32 | "IN": "India",
33 | "IL": "Israel",
34 | "CZ": "Czech Republic",
35 | "SE": "Sweden"
36 | }
37 |
38 | module.exports = {
39 | "apply_lang_to_code": function(code, req) {
40 | let lang = langs[this.get_language(req)] || langs.en
41 |
42 | for(let name in lang) {
43 | if(name == "footer_worldwide"
44 | && req.headers.cookie
45 | && req.headers.cookie.includes("gl=")) {
46 | let location = req.headers.cookie.split("gl=")[1].split(";")[0]
47 | let friendlyLocation = displayNames[location.toUpperCase()] || "?"
48 | code = code.split(`lang_${name}`).join(friendlyLocation)
49 | }
50 | code = code.split(`lang_${name}`).join(lang[name])
51 | }
52 |
53 | // english fallbacks
54 | if(code.includes("lang_")) {
55 | lang = langs.en
56 | for(let name in lang) {
57 | code = code.split(`lang_${name}`).join(lang[name])
58 | }
59 |
60 | }
61 |
62 | return code;
63 | },
64 |
65 | "get_language": function(req) {
66 | let lang = "en";
67 | if(typeof(req) == "string") {
68 | lang = req;
69 | }
70 | if((req.headers.cookie || "").includes("lang=")) {
71 | let langName = req.headers.cookie.split("lang=")[1].split(";")[0]
72 | lang = langName
73 | }
74 | if(req.query.hl) {
75 | lang = req.query.hl;
76 | }
77 | return lang;
78 | },
79 |
80 | "raw_language_data": function(lang) {
81 | return langs[lang] || langs["en"]
82 | },
83 |
84 | "get_language_list": function() {
85 | let langNames = {}
86 | for(let l in langs) {
87 | if(langs[l].footer_langname) {
88 | langNames[l] = langs[l].footer_langname
89 | }
90 | }
91 |
92 | return langNames;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/windowsxp.md:
--------------------------------------------------------------------------------
1 | # hosting yt2009 on windows xp
2 |
3 | as of yt2009 version 1.23.1, tests were done and patches were made to support hosting on windows xp,
4 |
5 | to the best of its abilities.
6 |
7 | **note that main "old" test version is node v14, and out-of-the-box compatibility limits to node v10 and above.**
8 |
9 | **valid issues will be accepted but will not be of high priority. issues about caveats (see down this page) will NOT be addressed.**
10 |
11 | ## prerequisites:
12 |
13 | - root certificates for HTTPS connections -- https://github.com/JohnTHaller/RootCertificateUpdatesForLegacyWindows
14 | - node v5.12.0 -- https://nodejs.org/download/release/v5.12.0/node-v5.12.0-x86.msi
15 | - ffmpeg -- https://sourceforge.net/projects/xpitory/files/ffmpeg/ffmpeg-3.4.1.7z/download (see **adding to PATH** section below)
16 | - magick -- http://archive.org/download/imagemagick-winxp/ImageMagick-6.9.11-19-Q8-x86-dll.exe (while installing, only have the PATH checkbox checked)
17 |
18 | ## adding to PATH
19 |
20 | as is the case with `ffmpeg`, or should you use any other binaries of required tools that don't ship with an installer, you must add them to your system's PATH environment variable.
21 |
22 | as of windows xp SP3:
23 | - open start menu, right click on `My Computer`, followed by `Properties`
24 | - open the `Advanced` tab, and click `Environment Variables`
25 | - depending on your setup, find the `PATH` variable in `User variables` or `System variables` and edit it.
26 | - within the `Variable value` textbox, add a `;` if there isn't one already at the end, and paste your **full** path where your binaries are.
27 | - press OK on all the popups, close the Properties window.
28 | - restart any CMD windows you might have had open for them to apply your new PATH.
29 |
30 | ## install steps
31 |
32 | - download the yt2009 code
33 | - open a CMD window and navigate it to the directory with all yt2009 files:
34 | ```
35 | cd "your_full_yt2009_path"
36 | ```
37 | - run these 2 commands to apply patches for older versions of dependencies and code:
38 | ```
39 | node strictifier.js
40 | node convertify.js
41 | ```
42 | **[!] these commands make significant code changes which will most likely mess with git, if you cloned the repository that way.**
43 | - install dependencies (old versions supported on xp):
44 | ```
45 | npm install express@4.17.1 google-protobuf@3.21.2 maxmind-db-reader node-fetch@2.0.0 node-html-parser@5.3.3 readline-sync ws@1.1.1
46 | ```
47 | - proceed with the setup as usual:
48 | ```
49 | node yt2009setup.js
50 | node post_config_setup.js
51 | cd back
52 | node backend.js
53 | ```
54 |
55 | ## caveats
56 |
57 | yt2009 will detect unsupported versions of node and apply appropriate patches.
58 |
59 | features affected simply cannot fully work on these old node versions with the way current-day youtube handles them.
60 |
61 | - **360p video only**
62 | - mobilehelper & pchelper severely disfunctional
63 | - sync server connection may not work properly
64 | - sabr streaming disabled
--------------------------------------------------------------------------------
/back/backend_wrap.js:
--------------------------------------------------------------------------------
1 | const child_process = require("child_process")
2 | const fetch = require("node-fetch")
3 | const fs = require("fs")
4 | const config = require("./config.json")
5 | const https = require("https")
6 | const yt2009utils = require("./yt2009utils")
7 | let yt2009_process;
8 |
9 | if(!fs.existsSync("./logs/")) {
10 | fs.mkdirSync("./logs/")
11 | }
12 | console.log("logs will be saved to /back/logs/")
13 |
14 | if(!fs.existsSync("./androiddata.json")) {
15 | const vids = [
16 | "evJ6gX1lp2o", "dQw4w9WgXcQ", "jNQXAC9IVRw",
17 | "yQwPhCI_qO0", "ts2a9cW4nLY"
18 | ]
19 | // test /player fetch to check if we need android sign in on host
20 | let rv = vids[Math.floor(Math.random() * vids.length)]
21 | fetch("https://www.youtube.com/youtubei/v1/player?prettyPrint=false", {
22 | "credentials": "include",
23 | "headers": {
24 | "Accept": "*/*",
25 | "Accept-Language": "pl,en-US;q=0.7,en;q=0.3",
26 | "Content-Type": "application/json",
27 | "x-goog-authuser": "0",
28 | "x-origin": "https://www.youtube.com/",
29 | "user-agent": "com.google.android.youtube/20.51.39 (Linux; U; Android 14) gzip",
30 | "cookie": require("./yt2009constants.json").headers.cookie
31 | },
32 | "agent": yt2009utils.createFetchAgent(),
33 | "referrer": "https://www.youtube.com/watch?v=" + rv,
34 | "body": JSON.stringify({
35 | "context": {
36 | "client": {
37 | "hl": "en",
38 | "clientName": "ANDROID",
39 | "clientVersion": "20.51",
40 | "mainAppWebInfo": {
41 | "graftUrl": "/watch?v=" + rv
42 | }
43 | }
44 | },
45 | "videoId": rv
46 | }),
47 | "method": "POST",
48 | "mode": "cors"
49 | }).then(r => {
50 | r.json().then(r => {
51 | if((r.playabilityStatus && r.playabilityStatus.status !== "OK"
52 | && r.playabilityStatus.reason
53 | && r.playabilityStatus.reason.includes("Sign in to confirm"))) {
54 | console.log(`
55 | =====================
56 |
57 | you might face trouble with video
58 | playback.
59 |
60 | run backend.js outside of
61 | backend_wrap for more info.
62 |
63 | =====================
64 |
65 | `)
66 | }
67 | })
68 | })
69 | }
70 |
71 | function start_yt2009() {
72 | let commands = [
73 | `cd "${__dirname.replace(/\"/g, "\\\"")}" `,
74 | `&& node backend.js`
75 | ].join("")
76 | console.log(`yt2009 start at ${new Date().toLocaleString()}`)
77 | yt2009_process = child_process.exec(commands, (error, stdout, stderr) => {
78 | fs.writeFileSync("./logs/" + Date.now() + ".txt", stdout + stderr)
79 | setTimeout(() => {
80 | start_yt2009()
81 | }, 3000)
82 | })
83 | }
84 | start_yt2009()
--------------------------------------------------------------------------------
/back/proto/sabr.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package sabr_request;
3 |
4 | message hwData {
5 | fixed32 id = 12;
6 | }
7 |
8 | message serviceIntegrityDimensionsMsg {
9 | message contents {
10 | optional bytes encryptData = 1;
11 | optional bytes tokenData = 2;
12 | }
13 | repeated contents content = 1;
14 | bytes webPot = 6;
15 | }
16 |
17 | message clientMsg {
18 | string deviceMake = 12;
19 | string deviceModel = 13;
20 | int32 clientNumber = 16;
21 | string clientVersion = 17;
22 | string osName = 18;
23 | string osVersion = 19;
24 | repeated hwData hw = 21;
25 | string gl = 22;
26 | string plreq = 25;
27 | int32 screenWidth = 37;
28 | int32 screenHeight = 38;
29 | int32 screenWidth2 = 55;
30 | int32 screenHeight2 = 56;
31 | optional int32 utcOffsetMinutes = 67;
32 | string timeZone = 80;
33 | string deviceCodename = 92;
34 | }
35 |
36 | message itagData {
37 | optional int32 itag = 1;
38 | int64 lastModifiedTime = 2;
39 | string drcString = 3; /*provided with audio itags, observed CggKA2RyYxIBMQ - 1:{1:"drc",2:"1"}*/
40 | /* ^^^ also used to specify audio track with xtags field if more present*/
41 | }
42 |
43 | message root {
44 | message timingData {
45 | /*all timestamp fields are in ms*/
46 | int32 absInitTime = 13; /*since page load begin -- not present on ANDROID*/
47 | int32 videoHeight = 16;
48 | int32 playerWidth = 18;
49 | int32 playerHeight = 19;
50 | int32 fiveInt = 27;
51 | optional int32 startTime = 28; /*where fetched data should start*/
52 | optional int32 reqInitTime = 29; /*since first sabr request?*/
53 | int32 fiveInt2 = 34;
54 | int32 relInitTime = 36; /*since player init*/
55 |
56 | /*more to be reversed*/
57 | }
58 | repeated timingData timing = 1;
59 |
60 | repeated itagData requestItag = 2;
61 |
62 | bytes config = 5; /* mediaCommonConfig -- sent in /player */
63 |
64 | message sourcePlayer {
65 | repeated clientMsg client = 1;
66 | repeated serviceIntegrityDimensionsMsg serviceIntegrityDimensions = 2; /*pot*/
67 |
68 | message abrRequestMsg {
69 | int32 height = 1;
70 | int32 twentyInt = 2; /*unknown, usually observed 20*/
71 | repeated itagData videoItag = 7;
72 | repeated itagData audioItag = 8;
73 | bytes playbackCookie = 20; /*contained within previous sabr response, empty if first*/
74 | }
75 | repeated abrRequestMsg abrRequest = 3;
76 |
77 | /*unknown defs below! 4.3.1 ranges 1-5*/
78 | message fourMsg {
79 | message threeMsg {
80 | int32 one = 1;
81 | }
82 | repeated threeMsg three = 3;
83 | }
84 | repeated fourMsg four = 4;
85 | }
86 |
87 | repeated itagData playableAudioItag = 16;
88 | repeated itagData playableVideoItag = 17;
89 |
90 | repeated sourcePlayer playerReq = 19;
91 | optional int32 videoItag = 22;
92 | optional int32 audioItag = 23;
93 | }
--------------------------------------------------------------------------------
/back/proto/android_search.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 | package android_search;
3 |
4 | message textRuns {
5 | message textRun {
6 | string text = 1;
7 | }
8 | repeated textRun run = 1;
9 | }
10 | message simpleText {
11 | string text = 4;
12 | }
13 | message thumbnails {
14 | message thumbnail {
15 | string url = 1;
16 | int32 width = 2;
17 | int32 height = 3;
18 | }
19 | repeated thumbnail thumb = 1;
20 | }
21 | message browseNavigation {
22 | message browseData {
23 | string browseId = 2;
24 | string params = 3;
25 | string canonicalBaseUrl = 4;
26 | }
27 | repeated browseData data = 48687626;
28 | }
29 | message authorData {
30 | message authorDataContent {
31 | string authorDisplayName = 1;
32 | optional browseNavigation navigation = 5;
33 | }
34 | optional authorDataContent ac = 1;
35 | }
36 | message navigationData {
37 | message navData {
38 | string navId = 1;
39 | }
40 | optional navData navProperties = 48687757;
41 | }
42 | message compactVideoRenderer {
43 | string videoId = 1;
44 | optional thumbnails thumblist = 2;
45 | optional textRuns titleData = 3;
46 | optional authorData shortAuthorData = 4;
47 | optional textRuns publishedTimeText = 5;
48 | optional textRuns viewCountText = 6;
49 | optional textRuns lengthText = 7;
50 | optional navigationData navData = 8;
51 | optional authorData longAuthorData = 10;
52 | optional thumbnails authorAvatar = 14;
53 | optional textRuns shortViewCounts = 23;
54 | }
55 | message playlistRenderer {
56 | string id = 1;
57 | optional thumbnails thumbnail = 2;
58 | optional textRuns playlistName = 3;
59 | optional authorData shortOwner = 4;
60 | optional textRuns videoCount = 5;
61 | optional browseNavigation playlistBrowse = 6;
62 | optional textRuns bareVideoCount = 9;
63 | optional thumbnails separatedThumbnail = 13;
64 | optional textRuns videoCount2 = 15;
65 | string webUrl = 19;
66 | optional authorData longOwner = 21;
67 | }
68 | message channelRenderer {
69 | string id = 1;
70 | optional thumbnails avatar = 2;
71 | optional textRuns name = 3;
72 | optional textRuns subCount = 4;
73 | optional textRuns handle = 5;
74 | optional browseNavigation navigation = 6;
75 | optional textRuns name2 = 9;
76 | optional thumbnails avatar2 = 16;
77 | }
78 | message root {
79 | message contents {
80 | message searchResults {
81 | message contents {
82 | message itemSectionRender {
83 | message contents {
84 | repeated compactVideoRenderer video = 50630979;
85 | repeated playlistRenderer playlist = 50742631;
86 | repeated channelRenderer channel = 50794305;
87 | }
88 | repeated contents content = 1;
89 | }
90 | repeated itemSectionRender section = 50195462;
91 | }
92 | repeated contents content = 1;
93 | }
94 | repeated searchResults resultsContainer = 49399797;
95 | }
96 | repeated contents content = 4;
97 | }
--------------------------------------------------------------------------------
/assets/site-assets/yt2009advsearch.js:
--------------------------------------------------------------------------------
1 | var advSearchOpened = false;
2 | function toggleAdvSearch() {
3 | advSearchOpened = !advSearchOpened
4 | if(advSearchOpened) {
5 | document.getElementById("search-advanced-form").className = ""
6 | } else {
7 | document.getElementById("search-advanced-form").className = "hid"
8 | }
9 | }
10 |
11 | function sendAdvSearch() {
12 | var urlAdded = ""
13 | // check for each option
14 | // textboxes
15 | var all_words = document.getElementById("input-all-words").value
16 | if(all_words) {
17 | urlAdded += all_words.split(" ").join("+")
18 | }
19 | var exact_phrase = document.getElementById("input-exact").value
20 | if(exact_phrase) {
21 | urlAdded += "+\"" + exact_phrase.split(" ").join("+") + "\""
22 | }
23 | var one_or_more = document.getElementById("input-one-or-more").value
24 | if(one_or_more) {
25 | urlAdded += "+(" + one_or_more.split(" ").join("+OR+") + ")"
26 | }
27 | var none = document.getElementById("input-none").value
28 | if(none) {
29 | urlAdded += "+-" + none.split(" ").join("+-")
30 | }
31 | // type of results
32 | var checkedType;
33 | var checkedFeatures = []
34 | var inputs = document.getElementById("panel2").getElementsByTagName("input")
35 | for(var input in inputs) {
36 | input = inputs[input]
37 | if(input.nodeName
38 | && input.getAttribute("type") == "radio"
39 | && input.checked) {
40 | checkedType = input;
41 | }
42 | if(input.nodeName
43 | && input.getAttribute("type") == "checkbox"
44 | && input.checked) {
45 | checkedFeatures.push(input)
46 | }
47 | }
48 | for(var feature in checkedFeatures) {
49 | urlAdded += "&" + checkedFeatures[feature].getAttribute("name") + "=1"
50 | }
51 | if(checkedType && checkedType.id !== "radio-all") {
52 | urlAdded += "&search_type=search_" + checkedType.id.replace("radio-", "")
53 | }
54 |
55 | // duration
56 | var selectedDuration = false
57 | var durations = document.getElementById("select-duration")
58 | .getElementsByTagName("option")
59 | for(var duration in durations) {
60 | if(durations[duration] && durations[duration].selected) {
61 | selectedDuration = durations[duration]
62 | }
63 | }
64 | if(selectedDuration.getAttribute("name")
65 | && selectedDuration.getAttribute("name") !== "anytime") {
66 | urlAdded += "&search_duration=" + selectedDuration.getAttribute("name")
67 | }
68 |
69 | // upload time
70 | var selectedTime = false
71 | var times = document.getElementById("select-uploaded")
72 | .getElementsByTagName("option")
73 | for(var time in times) {
74 | if(times[time] && times[time].selected) {
75 | selectedTime = times[time]
76 | }
77 | }
78 | if(selectedTime.getAttribute("name")
79 | && selectedTime.getAttribute("name") !== "anytime") {
80 | urlAdded += "&uploaded=" + selectedTime.getAttribute("name")
81 | }
82 |
83 | // send!!
84 | location.href = YT2009_BASE_SEARCH_URL + urlAdded
85 | }
--------------------------------------------------------------------------------
/mobile/search.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
YouTube - Broadcast Yourself.
6 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Sign In
25 |
26 |
27 |
28 |
29 |
37 |
38 |
43 |
44 |
50 |
51 |
52 |
53 |
60 |
67 |
68 |
Mobile
69 | |
Desktop
70 |
© 2009 YouTube, LLC
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/assets/site-assets/inbox_css.css:
--------------------------------------------------------------------------------
1 | /*
2 | code matched from half-working archives of mid-2010 inbox and videos from 2009.
3 |
4 | resources:
5 | http://web.archive.org/web/20100725215724/http://www.youtube.com/inbox
6 | https://www.youtube.com/watch?v=iaNFp2ZC2hA
7 | https://www.youtube.com/watch?v=uR70ak_xWgM
8 | https://www.youtube.com/watch?v=Qv4TZfrBmYY
9 |
10 | don't expect 100% accuracy as it isn't original yt code
11 | but an attempt was made.
12 | */
13 | #message_reading, .view {
14 | min-height: 600px;
15 | }
16 | #heading-from, .from {
17 | width: 130px;
18 | min-width: 130px;
19 | }
20 | #heading-subject, .subject {
21 | width: 389px;
22 | min-width: 389px;
23 | max-width: 389px;
24 | }
25 | #heading-date, .date {
26 | width: 175px;
27 | min-width: 175px;
28 | }
29 | #headings {
30 | width: 750px;
31 | display: block;
32 | }
33 | .message.even {
34 | background-color: #f3f3f3;
35 | }
36 | .message.closed {
37 | height: 25px;
38 | cursor: pointer;
39 | }
40 | .message.open {
41 | cursor: pointer;
42 | }
43 | .message .check {
44 | padding: 2px 4px;
45 | width: 25px;
46 | max-width: 25px;
47 | }
48 | .empty {
49 | color: #555;
50 | margin-top: 20px;
51 | text-align: center;
52 | }
53 | .folder {
54 | cursor: pointer;
55 | }
56 | .message.open .collapsed {
57 | display: none;
58 | }
59 | .message.open .expanded {
60 | display: table-cell;
61 | }
62 | .message.closed .expanded {
63 | display: none;
64 | }
65 | .from img {
66 | display: block;
67 | overflow: hidden;
68 | border: 3px double #999;
69 | width: 55px;
70 | height: 55px;
71 | margin-top: 5px;
72 | }
73 | .open .check {
74 | vertical-align: top;
75 | }
76 | .open .check input {
77 | margin-top: 4px;
78 | }
79 | .open .subject {
80 | vertical-align: top;
81 | padding-top: 4px;
82 | }
83 | .from.expanded, .date.expanded {
84 | vertical-align: top;
85 | }
86 | .v120WideEntry {
87 | float: left;
88 | margin-right: 5px;
89 | }
90 | .video-main-content {
91 | width: 265px;
92 | max-width: 265px;
93 | float: left;
94 | overflow: hidden;
95 | }
96 | .video-description {
97 | color: #000;
98 | height: 65px;
99 | }
100 | .date.expanded {
101 | padding-top: 5px;
102 | }
103 | .subject.expanded #button-delete {
104 | margin-bottom: 7px;
105 | }
106 | .composeform {
107 | padding: 1em
108 | }
109 | .reply_header {
110 | text-align: left;
111 | color: #333;
112 | width: 100px;
113 | vertical-align: top;
114 | padding-top: 0.75em
115 | }
116 | .reply_body {
117 | padding-top: 0.75em;
118 | color: #666
119 | }
120 | .compose_header {
121 | text-align: right;
122 | color: #333;
123 | width: 100px;
124 | padding-right: 1em;
125 | vertical-align: top;
126 | padding-top: 1.25em
127 | }
128 | .compose_body {
129 | text-align: left;
130 | padding: 0;
131 | padding-top: 1em;
132 | color: #666
133 | }
134 | .compose_body div {
135 | padding-top: 0.25em
136 | }
137 | .compose_input {
138 | width: 90%;
139 | font-family: Arial, Helvetica, sans-serif;
140 | font-size: 10pt
141 | }
142 | #message_composing.not_allowed, #message_composing.not_allowed * {
143 | cursor: not-allowed;
144 | }
--------------------------------------------------------------------------------
/back/cache_dir/ryd_cache_manager.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs")
2 | const fetch = require("node-fetch")
3 | const utils = require("../yt2009utils")
4 | const config = require("../config.json")
5 | let cache = {}
6 | if(!config.fallbackMode) {
7 | try {
8 | cache = JSON.parse(fs.readFileSync(`${__dirname}/ryd_cache.json`).toString())
9 | }
10 | catch(error) {}
11 | }
12 | let ongoingFetches = []
13 | let ongoingCallbacks = {}
14 |
15 | module.exports = {
16 | "fetch": function(id, callback) {
17 | id = id.substring(0, 11);
18 |
19 | if(cache[id]) {
20 | callback(cache[id])
21 | } else {
22 | ongoingFetches.push(id)
23 | fetch(`https://returnyoutubedislikeapi.com/votes?videoId=${id}`, {
24 | "headers": {
25 | "user-agent": "yt2009 / twt@ybnn670"
26 | }
27 | }).then(r => {
28 | r.json().catch(error => {callback(5)}).then(response => {
29 | if(!response
30 | || !response.rating) {
31 | callback(5)
32 | cache[id] = 5
33 | return;
34 | }
35 | callback(utils.custom_rating_round(response.rating))
36 | cache[id] = utils.custom_rating_round(response.rating)
37 | ongoingFetches = ongoingFetches.filter(s => {
38 | return s !== id
39 | })
40 | if(ongoingCallbacks[id]) {
41 | ongoingCallbacks[id].forEach(f => {f()})
42 | ongoingCallbacks[id] = []
43 | }
44 | })
45 | }).catch(error => {
46 | console.log("[e] return youtube dislike api failed to load!", error)
47 | callback(5)
48 | ongoingFetches = ongoingFetches.filter(s => {
49 | return s !== id
50 | })
51 | if(ongoingCallbacks[id]) {
52 | ongoingCallbacks[id].forEach(f => {f()})
53 | ongoingCallbacks[id] = []
54 | }
55 | })
56 | }
57 | },
58 |
59 | "readCache": function(id) {
60 | // read only if the video is in cache, otherwise undefined
61 | return cache[id];
62 | },
63 |
64 | "readWait": function(id, callback) {
65 | if(cache[id]) {
66 | callback(cache[id])
67 | return;
68 | }
69 |
70 | // if ongoing, wait for the result
71 | if(ongoingFetches.includes(id)) {
72 | if(!ongoingCallbacks[id]) {
73 | ongoingCallbacks[id] = []
74 | }
75 | ongoingCallbacks[id].push(function() {
76 | if(cache[id]) {
77 | //console.log("ryd received")
78 | callback(cache[id])
79 | } else {
80 | callback(5)
81 | }
82 | })
83 | return;
84 | }
85 |
86 | // fallback: pull clean
87 | this.fetch(id, callback)
88 | }
89 | }
90 |
91 | // update pliku cache co 1h
92 | let cacheWrite = setInterval(() => {
93 | if(config.fallbackMode) return;
94 | fs.writeFileSync(`${__dirname}/ryd_cache.json`, JSON.stringify(cache))
95 | }, 3600000)
--------------------------------------------------------------------------------
/back/yt2009loginsimulate.js:
--------------------------------------------------------------------------------
1 | const base_code_logged_in = `
2 |
3 |
22 |
23 | `
24 |
25 | const base_code_logged_out = `
26 |
27 | Create Account
28 | or
29 | Sign In
30 | `
31 |
32 | module.exports = function(req, code, returnNoLang) {
33 | let flags = req.query && req.query.flags ? req.query.flags + ":" : ""
34 | try {
35 | req.headers.cookie.split(";").forEach(cookie => {
36 | if(cookie.trimStart().startsWith("global_flags")) {
37 | flags += cookie.trimStart().replace("global_flags=", "")
38 | }
39 | })
40 | }
41 | catch(error) {
42 | flags = req;
43 | }
44 |
45 | let loggedInUsername = false;
46 |
47 | try {
48 | flags = flags.split(";").join(":")
49 | flags.split(":").forEach(flag => {
50 | if(flag.includes("login_simulate")) {
51 | loggedInUsername = flag.split("login_simulate")[1];
52 | }
53 | })
54 | }
55 | catch(error) {
56 | // ej ej ej ale bez takich
57 | if(req.headers["user-agent"] == "Shockwave Flash") {
58 | return "";
59 | }
60 | }
61 |
62 | if(loggedInUsername) {
63 | loggedInUsername = require("./yt2009utils").asciify(
64 | decodeURIComponent(loggedInUsername), true, true
65 | ).substring(0, 20)
66 | if(loggedInUsername.length == 0) {
67 | loggedInUsername = "guest"
68 | }
69 | code = code.replace(
70 | "",
71 | base_code_logged_in.split("yt2009_username").join(
72 | loggedInUsername
73 | )
74 | )
75 | } else {
76 | code = code.replace("", base_code_logged_out)
77 | }
78 |
79 | // languages via hl param/lang cookie
80 | if(returnNoLang) {
81 | code = code.replace(`Sign Out`, "lang_signout_btn")
82 | code = code.replace(`Create Account`, "lang_create_btn")
83 | code = code.replace(`>or<`, ">lang_or<")
84 | code = code.replace(`Sign In`, "lang_sign_btn")
85 | }
86 |
87 | return code;
88 | }
--------------------------------------------------------------------------------
/back/cache_dir/captions_cache_mgr.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs")
2 | const fetch = require("node-fetch")
3 | const constants = require("../yt2009constants.json")
4 | const config = require("../config.json")
5 | const yt2009html = require("../yt2009html")
6 | const yt2009exports = require("../yt2009exports")
7 | let cache = {}
8 | if(!config.fallbackMode) {
9 | try {
10 | cache = JSON.parse(fs.readFileSync(`${__dirname}/captions_cache.json`).toString())
11 | }
12 | catch(error) {}
13 | }
14 |
15 | module.exports = {
16 | "write": function(id, data) {
17 | cache[id] = data;
18 | },
19 |
20 | "read": function(id, callback, resetCache) {
21 | if(cache[id] && !resetCache) {
22 | callback(cache[id])
23 | } else {
24 | // clean fetch
25 | let languages = {}
26 | function parsePlayer(data) {
27 | if(data.captions) {
28 | try {
29 | let cc = data.captions.playerCaptionsTracklistRenderer
30 | .captionTracks
31 | let nonasrLangs = []
32 | let nonAsr = cc.filter(s => {
33 | if(!s.kind) {
34 | nonasrLangs.push(s.languageCode)
35 | }
36 | return !s.kind
37 | })
38 | let asr = cc.filter(s => {
39 | return s.kind
40 | && !nonasrLangs.includes(s.languageCode)
41 | })
42 | let merged = []
43 | nonAsr.forEach(c => {merged.push(c)})
44 | asr.forEach(c => {merged.push(c)})
45 | merged.forEach(track => {
46 | let name = track.name.simpleText || ""
47 | if(track.name && track.name.runs) {
48 | name = track.name.runs[0].text
49 | }
50 | if(track.baseUrl.includes("fmt=")) {
51 | let fmt = track.baseUrl.split("fmt=")[1].split("&")[0]
52 | track.baseUrl = track.baseUrl.replace("&fmt=" + fmt, "")
53 | }
54 | languages[track.languageCode] = {
55 | "name": name,
56 | "url": track.baseUrl || ""
57 | }
58 | })
59 | }
60 | catch(error) {console.log(error)}
61 | }
62 | callback(languages)
63 | cache[id] = languages;
64 | //this.write(id, languages)
65 | }
66 | if(yt2009exports.read().players[id]) {
67 | parsePlayer(yt2009exports.read().players[id])
68 | setTimeout(() => {
69 | yt2009exports.delete("players", id)
70 | }, 200)
71 | } else {
72 | yt2009html.innertube_get_data(id, (player) => {
73 | parsePlayer(player)
74 | })
75 | }
76 | }
77 | }
78 | }
79 |
80 |
81 | // update pliku cache co 1h
82 | let cacheWrite = setInterval(() => {
83 | if(config.fallbackMode) return;
84 | fs.writeFileSync(`${__dirname}/captions_cache.json`, JSON.stringify(cache))
85 | }, 3600000)
--------------------------------------------------------------------------------
/assets/site-assets/leanback_ajax.json:
--------------------------------------------------------------------------------
1 | {"sets": [{"title": "YouTube Trends", "video_count": 4777, "gdata_list_id": "FLtrends", "icon": "trends", "gdata_url": "\/feeds\/api\/users\/trends\/favorites", "list_id": "FLeNZlh03MyUkjRlLFpVQxsg", "tab": "featured", "thumbnail": "http:\/\/i1.ytimg.com\/vi\/6ravZzYKR34\/hqdefault.jpg"}, {"title": "Music", "video_count": 30, "gdata_list_id": "STmost_popular_Music", "icon": "music", "gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_Music?time=today", "list_id": "LBpop,10,t,en_US", "tab": "featured", "thumbnail": "http:\/\/i1.ytimg.com\/vi\/_vw2K0AgFF0\/hqdefault.jpg"}, {"title": "Gaming", "video_count": 30, "gdata_list_id": "STmost_popular_Games", "icon": "gaming", "gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_Games?time=today", "list_id": "LBpop,20,t,en_US", "tab": "featured", "thumbnail": "http:\/\/i1.ytimg.com\/vi\/7WJBJ9OI1ds\/hqdefault.jpg"}, {"title": "Sports", "video_count": 30, "gdata_list_id": "STmost_popular_Sports", "icon": "sports", "gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_Sports?time=today", "list_id": "LBpop,17,t,en_US", "tab": "featured", "thumbnail": "http:\/\/i1.ytimg.com\/vi\/vu1zMV5j0fo\/hqdefault.jpg"}, {"title": "Film \u0026 Animation", "video_count": 30, "gdata_list_id": "STmost_popular_Film", "icon": "film", "gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_Film?time=today", "list_id": "LBpop,1,t,en_US", "tab": "featured", "thumbnail": "http:\/\/i1.ytimg.com\/vi\/DfSyyw8duQ0\/hqdefault.jpg"}, {"gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_Entertainment?time=today", "title": "Entertainment", "tab": "featured", "icon": "entertainment", "gdata_list_id": "STmost_popular_Entertainment"}, {"gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_Comedy?time=today", "title": "Comedy", "tab": "featured", "icon": "comedy", "gdata_list_id": "STmost_popular_Comedy"}, {"gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_News?time=today", "title": "News \u0026 Politics", "tab": "featured", "icon": "news", "gdata_list_id": "STmost_popular_News"}, {"gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_People?time=today", "title": "People \u0026 Blogs", "tab": "featured", "icon": "people", "gdata_list_id": "STmost_popular_People"}, {"gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_Tech?time=today", "title": "Science \u0026 Technology", "tab": "featured", "icon": "tech", "gdata_list_id": "STmost_popular_Tech"}, {"gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_Howto?time=today", "title": "Howto \u0026 Style", "tab": "featured", "icon": "howto", "gdata_list_id": "STmost_popular_Howto"}, {"gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_Education?time=today", "title": "Education", "tab": "featured", "icon": "education", "gdata_list_id": "STmost_popular_Education"}, {"gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular_Animals?time=today", "title": "Pets \u0026 Animals", "tab": "featured", "icon": "animals", "gdata_list_id": "STmost_popular_Animals"}, {"gdata_url": "\/feeds\/api\/users\/Y30JRSgfhYXA6i6xX1erWg\/uploads", "title": "Smosh", "tab": "featured", "gdata_list_id": "UUY30JRSgfhYXA6i6xX1erWg"}, {"gdata_url": "\/feeds\/api\/users\/aBf1a-dpIsw8OxqH4ki2Kg\/uploads", "title": "Geek \u0026 Sundry", "tab": "featured", "gdata_list_id": "UUaBf1a-dpIsw8OxqH4ki2Kg"}, {"title": "Most Popular", "video_count": 30, "gdata_list_id": "STmost_popular", "icon": "popular", "gdata_url": "\/feeds\/api\/standardfeeds\/US\/most_popular?time=today", "list_id": "LBpop,0,t,en_US", "tab": "featured", "thumbnail": "http:\/\/i1.ytimg.com\/vi\/1b1loWJfxaA\/hqdefault.jpg"}]}
--------------------------------------------------------------------------------
/back/yt2009mobileflags.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs")
2 | // create cache entry for serverside flags if nonexistent
3 | if(!fs.existsSync("./cache_dir/mobile_flags.json")) {
4 | fs.appendFileSync("./cache_dir/mobile_flags.json", "{}")
5 | }
6 | const mflags = require("./cache_dir/mobile_flags.json")
7 | const knownFlagNames = {
8 | "watch": ["new-related", "innertube-related", "realistic-view-count", "better-hd"],
9 | "search": ["only-old"],
10 | "channel": ["default-avatar-adapt", "uploads-count", "uncrop-avatar"]
11 | }
12 | let sessions = {}
13 |
14 | module.exports = {
15 | "request_session": function(req, res) {
16 | res.sendStatus(200)
17 | },
18 |
19 | "write_session": function(ip, deviceId) {
20 | sessions[ip] = deviceId
21 | },
22 |
23 | "get_session": function(req, res) {
24 | if(req.ip.includes("192.168.")) {
25 | let altSession = false;
26 | for(let ip in sessions) {
27 | if(ip.includes("192.168.")) {
28 | altSession = sessions[ip]
29 | }
30 | }
31 |
32 | if(!altSession) {
33 | res.sendStatus(404)
34 | return;
35 | }
36 |
37 | res.send(altSession)
38 | return;
39 | }
40 | if(sessions[req.ip]) {
41 | res.send(sessions[req.ip])
42 | } else {
43 | res.sendStatus(404)
44 | }
45 | },
46 |
47 | "save_flags": function(req, res) {
48 | // filter and parse
49 | let body = JSON.parse(req.body.toString())
50 | if(!body["watch"]
51 | || !body["search"]
52 | || !body["channel"]
53 | || !req.headers["device"]) {
54 | res.sendStatus(400)
55 | return;
56 | }
57 | let filteredUserFlags = {
58 | "watch": [], "search": [], "channel": [], "login_simulate": ""
59 | }
60 | body.watch.forEach(flag => {
61 | if(knownFlagNames.watch.includes(flag)) {
62 | filteredUserFlags.watch.push(flag)
63 | }
64 | })
65 | body.search.forEach(flag => {
66 | if(knownFlagNames.search.includes(flag)) {
67 | filteredUserFlags.search.push(flag)
68 | }
69 | })
70 | body.channel.forEach(flag => {
71 | if(knownFlagNames.channel.includes(flag)) {
72 | filteredUserFlags.channel.push(flag)
73 | }
74 | })
75 | if(body.login_simulate && body.login_simulate.includes("/")) {
76 | filteredUserFlags.login_simulate = body.login_simulate
77 | }
78 |
79 | // push
80 | mflags[req.headers.device] = filteredUserFlags
81 | fs.writeFileSync(
82 | "./cache_dir/mobile_flags.json",
83 | JSON.stringify(mflags)
84 | )
85 | res.sendStatus(200)
86 | },
87 |
88 | "get_flags": function(req) {
89 | let flags = {"watch": [], "search": [], "channel": []}
90 | if(req.headers["x-gdata-device"]
91 | && req.headers["x-gdata-device"].includes("device-id=\"")) {
92 | let deviceId = req.headers["x-gdata-device"]
93 | .split("device-id=\"")[1]
94 | .split("\"")[0];
95 | if(mflags[deviceId]) {
96 | flags = mflags[deviceId]
97 | }
98 | }
99 |
100 | return flags;
101 | }
102 | }
--------------------------------------------------------------------------------
/convertify.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | // convertify -- use "convert" instead of "magick" (magick v6),
4 | // and patch functions for node v5
5 |
6 | let major = -1
7 | try {
8 | major = parseInt(process.version.replace("v", "").split(".")[0])
9 | }
10 | catch(error) {}
11 |
12 | if(major >= 6 && process.argv.indexOf("--bypass-version-check") == -1) {
13 | console.log(`
14 | =======
15 |
16 | [!] your nodejs version appears to be
17 | new enough to not need those patches,
18 |
19 | and they will most likely cause more
20 | trouble than use.
21 |
22 | heavily not recommended, but you can use
23 | --bypass-version-check to get around
24 | this message.
25 |
26 | ======`)
27 | process.exit()
28 | return;
29 | }
30 |
31 | console.log("// applying magick->convert patches")
32 |
33 | const fs = require("fs")
34 | const convertFiles = [
35 | "post_config_setup.js",
36 | "back/backend.js",
37 | "back/detect_default_avatar.js",
38 | "back/dominant_color.js",
39 | "back/yt2009charts.js",
40 | "back/yt2009mobile.js"
41 | ]
42 |
43 | convertFiles.forEach(f => {
44 | let content = fs.readFileSync(f).toString()
45 | content = content.split(`, "magick --help"`).join("")
46 | content = content.split(`, "convert --help"`).join("")
47 | content = content.split("magick convert").join("convert")
48 | content = content.split("\"magick").join("\"convert")
49 | content = content.split("`magick").join("`convert")
50 | fs.writeFileSync(f, content)
51 | console.log(`processed ${f}`)
52 | })
53 |
54 | // trimStart() and trimEnd() exist in node v5 but crash the whole process
55 | // replace with trimLeft() and trimRight()
56 |
57 | console.log("\n\n\n// applying string trim fixes (es6)")
58 | const trimFiles = [
59 | "post_config_setup.js",
60 | "back/"
61 | ]
62 |
63 | function trimFix(content) {
64 | return content
65 | .split("trimStart(").join("trimLeft(")
66 | .split("trimEnd(").join("trimRight(")
67 | .split("trim()").join("trimLeft().trimRight()")
68 | }
69 |
70 | trimFiles.forEach(f => {
71 | if(f.endsWith("/")) {
72 | // is a directory
73 | fs.readdirSync(f).forEach(file => {
74 | if(file.endsWith(".js")) {
75 | let path = f + file
76 | let content = fs.readFileSync(path).toString()
77 | content = trimFix(content)
78 | fs.writeFileSync(path, content)
79 | console.log(`processed ${path}`)
80 | }
81 | })
82 | } else {
83 | // is a file
84 | let content = fs.readFileSync(f).toString()
85 | content = trimFix(content)
86 | fs.writeFileSync(f, content)
87 | console.log(`processed ${f}`)
88 | }
89 | })
90 |
91 | try {fs.unlinkSync(__dirname + "/Dockerfile")}catch(error){}
92 |
93 | // bigint patchout
94 | console.log("\n\n\napplying bigint nuke")
95 | let htmlCode = fs.readFileSync("./back/yt2009html.js").toString()
96 | htmlCode = htmlCode.split("BigInt").join("")
97 | fs.writeFileSync("./back/yt2009html.js", htmlCode)
98 | console.log("..done!")
99 |
100 | // regex fixup
101 | console.log("\n\n\napplying regex patch")
102 | htmlCode = htmlCode.split("/gui").join("/gi")
103 | fs.writeFileSync("./back/yt2009html.js", htmlCode)
104 | let utilsCode = fs.readFileSync("./back/yt2009utils.js").toString()
105 | utilsCode = utilsCode.split("/gui").join("/gi")
106 | fs.writeFileSync("./back/yt2009utils.js", utilsCode)
107 | console.log("..done!")
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # yt2009 temp assets, things that change over time
2 | media/
3 | assets/*.mp4
4 | assets/*.ogg
5 | assets/*.flv
6 | assets/*.png
7 | assets/*.jpg
8 | assets/*.3gp
9 | assets/*.mp3
10 | assets/*.m4a
11 | assets/*.wmv
12 | assets/*.avi
13 | assets/charts_temp/
14 | assets/user-uploads-tmp/
15 | back/cache_dir/annotations/*
16 | back/cache_dir/*.json
17 | back/config.json
18 | player-imgs/temp/
19 | player-imgs/embed-bgs/user-gen/*
20 | relay/relay-script/config.json
21 | relay/relay-script/userdata.json
22 | mobile/*.mp4
23 | mobile/*.3gp
24 | mobile/*.ogg
25 | changelogs/*.txt
26 | apksetup/
27 | back/logs/
28 | back/tvdata.json
29 | back/androiddata.json
30 | back/mobilehelper_userdata.json
31 | back/autoshare_userdata
32 |
33 | # yt assets
34 | master-vfl121679.png
35 | video_bar_arrows-vfl84478.png
36 | favicon.ico
37 | assets/site-assets/active_sharing_on-vfl70992.png
38 | assets/site-assets/activity_indicator-vfl120761.gif
39 | assets/site-assets/annotations_editor_switch-vfl78622.gif
40 | assets/site-assets/annotations_icon-vfl78622.gif
41 | assets/site-assets/apple-touch-icon2-vfl171763.png
42 | assets/site-assets/arrow_dropdown-vfl29016.gif
43 | assets/site-assets/autoshare-vfl137249.png
44 | assets/site-assets/background-drop-fade-vfl85178.gif
45 | assets/site-assets/badge_annotate-vfl55396.gif
46 | assets/site-assets/badge_cc_domestic-vfl55396.gif
47 | assets/site-assets/badge_cc_intl-vfl55396.gif
48 | assets/site-assets/badge_featurelength-vfl55396.gif
49 | assets/site-assets/blazer_sprite_high-vfl176462.png
50 | assets/site-assets/blazer_sprite_low-vfl176462.png
51 | assets/site-assets/blazer_sprite_vhigh-vfl176746.png
52 | assets/site-assets/but-bck-vfl33160.png
53 | assets/site-assets/button_icons-vfl72305.png
54 | assets/site-assets/cart_icons-vfl115610.png
55 | assets/site-assets/channel_iconset-vfl65968.gif
56 | assets/site-assets/channel-bg-sprites-vfl91176.png
57 | assets/site-assets/channel-sprites-vfl115627.gif
58 | assets/site-assets/close-vfl69806.png
59 | assets/site-assets/contentid-cm-logo-vfl85500.jpg
60 | assets/site-assets/contentid-tick-vfl85500.jpg
61 | assets/site-assets/creatorscorner-vfl114850.png
62 | assets/site-assets/drop_shadow-vfl111653.png
63 | assets/site-assets/embed_selection-vfl81006.png
64 | assets/site-assets/faketrans-vfl35975.gif
65 | assets/site-assets/flags-vfl57703.gif
66 | assets/site-assets/forums_master-vfl68068.gif
67 | assets/site-assets/icn_cycds_warning-vfl33982.gif
68 | assets/site-assets/icn_loading_animated-vfl24663.gif
69 | assets/site-assets/icn_star_full_11x11.gif
70 | assets/site-assets/img_about_toexternal_14x9-vfl35309.gif
71 | assets/site-assets/iyt-vfl105161.png
72 | assets/site-assets/logo_content-id_352x109-vfl100716.png
73 | assets/site-assets/longform-underlay-1x1-vfl55396.png
74 | assets/site-assets/master_old-vfl72391.gif
75 | assets/site-assets/mmgrads-vfl38740.gif
76 | assets/site-assets/mmimgs-vfl38740.gif
77 | assets/site-assets/pic_ytlogo_58x20-vfl124299.gif
78 | assets/site-assets/pixel-vfl73.gif
79 | assets/site-assets/play_all_small-vfl82345.png
80 | assets/site-assets/playlist_row_deleter-vfl69806.png
81 | assets/site-assets/profile-vfl30243.gif
82 | assets/site-assets/sel-bck-omar-vfl34546.png
83 | assets/site-assets/sharing_icons-vfl84489.png
84 | assets/site-assets/silver-grad-vfl35285.png
85 | assets/site-assets/stars_5.0_49x9-vfl84759.gif
86 | assets/site-assets/tooltip-reverse-vfl88394.gif
87 | assets/site-assets/tooltip-vfl56131.gif
88 | assets/site-assets/ugcpromo_tagline_bg-vfl91176.gif
89 | assets/site-assets/video_bar_arrows-vfl84478.png
90 | assets/site-assets/video_cluster_180_border-vfl88394.png
91 | assets/site-assets/yt-narrative-tail-vfl55396.gif
--------------------------------------------------------------------------------
/mobile/blzr/flags.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
yt2009 blazer flags
7 |
8 |
9 |
10 |
11 |
yt2009 blazer flags
12 |
modify your blazer experience - a 2010 webapp. try at /mobile/blzr .
13 |
--------
14 | getting an "In order to watch videos, please enable plugins in Safari Settings." error?
15 | try requesting a desktop site or enabling the no_warning flag.
16 | --------
17 |
18 |
videos
19 |
20 |
21 |
comments_fake_dates
22 |
shows the comment time relative to 2012
23 |
24 |
25 |
26 |
fix_btn
27 |
center the play button as it may appear to the left on some platforms
28 |
29 |
30 |
31 |
innertube_related
32 |
show default related section returned by youtube
33 |
34 |
35 |
36 |
new_related
37 |
legacy remove the date filter for exp_related
38 |
39 |
40 |
41 |
no_warning
42 |
disables the plugin warning in ios safari.
43 |
44 |
45 |
46 |
undefault_avatar
47 |
doesn't use default_avataradapt for avatars.
48 |
49 |
50 |
51 |
search
52 |
53 |
54 |
only_old
55 |
only show old videos in search results
56 |
57 |
58 |
59 |
global
60 |
61 |
62 |
login_simulate
63 |
64 |
make blazer think you're logged in, enabling things like playlists.
65 |
66 |
67 |
save
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/mobile/view-comment.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
YouTube - Broadcast Yourself.
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Comments
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 | yt2009_length
35 | yt2009_publish
36 | yt2009_views
37 | yt2009_uploader
38 |
39 |
40 |
41 |
42 |
45 |
46 |
47 |
48 |
55 |
56 |
57 |
58 |
65 |
70 |
71 |
Mobile
72 | |
Desktop
73 |
© 2009 YouTube, LLC
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------