yt-chan-cgi - randomcrap - random crap programs of varying quality
(HTM) git clone git://git.codemadness.org/randomcrap
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
yt-chan-cgi (3110B)
---
1 #!/bin/sh
2 # CGI program: combine Youtube Atom feed and channel videos.
3 # It adds video durations to the title and filters away Youtube
4 # shorts/announcements, etc.
5 # Dependencies: frontends/youtube/channel2tsv, sfeed, hurl, etc.
6
7 PATH="/cgi-bin/bin"
8
9 query="${REQUEST_URI}"
10 query="${query##/yt-chan/}"
11
12 format=""
13 case "${query}" in
14 *.json)
15 format="json"
16 query="${query%%.json}"
17 ;;
18 *.html)
19 format="html"
20 query="${query%%.html}"
21 ;;
22 *.twtxt)
23 format="twtxt"
24 query="${query%%.twtxt}"
25 ;;
26 *.txt)
27 format="txt"
28 query="${query%%.txt}"
29 ;;
30 *.xml)
31 format="xml"
32 query="${query%%.xml}"
33 ;;
34 esac
35
36 channelid="${query}"
37 channelid="${channelid##\?}"
38 channelid="${channelid##c=}"
39
40 if test "$channelid" = ""; then
41 printf 'Status: 400 Bad Request\r\n'
42 printf 'Content-Type: text/plain; charset=utf-8\r\n\r\n'
43 exit 1
44 fi
45
46 channelid="$(printf '%s' "$channelid" | sed -E 's@[^a-zA-Z0-9_-]*@@g')"
47 if test "$channelid" = ""; then
48 printf 'Status: 400 Bad Request\r\n'
49 printf 'Content-Type: text/plain; charset=utf-8\r\n\r\n'
50 printf "Channel ID must be set and proper: %s" "$channelid"
51 exit 1
52 fi
53
54 f1="$(mktemp)"
55 f2="$(mktemp)"
56 f3="$(mktemp)"
57
58 # delete temp file on exit.
59 trap 'rm -f "$f1" "$f2" "$f3"' EXIT
60
61 url="https://www.youtube.com/feeds/videos.xml?channel_id=${channelid}"
62 if ! hurl "$url" > "$f2"; then
63 printf 'Status: 400 Bad Request\r\n'
64 printf 'Content-Type: text/plain; charset=utf-8\r\n\r\n'
65 printf 'Could not get feed: %s' "$url"
66 exit 1
67 fi
68
69 # get channel data.
70 if ! channel2tsv "$channelid" > "$f1"; then
71 printf 'Status: 400 Bad Request\r\n'
72 printf 'Content-Type: text/plain; charset=utf-8\r\n\r\n'
73 printf 'Could not get channel videos: %s' "$channelid"
74 exit 1
75 fi
76
77 # combine data and output it.
78 sfeed < "$f2" | \
79 LC_ALL=C awk -v "f1=$f1" -v "f2=-" '
80 BEGIN {
81 FS = OFS = "\t";
82 }
83 FILENAME == f1 {
84 durations[$1] = $6;
85 }
86 FILENAME == f2 {
87 # quick way to get video ID after v parameter.
88 idx = index($3, "v=");
89 if (idx > 1) {
90 id = substr($3, idx + 2);
91
92 # Add duration to title if it can be found.
93 # Currently the channel videos page has 30 videos, the Atom
94 # feed has 15, so they usually match, Youitube shorts,
95 # upcoming video announcements or livestreams typically do not match.
96 # This is a feature imho, because it allows filtering them away.
97 if (durations[id])
98 $2 = $2 " [" durations[id] "]";
99 }
100 print $0;
101 }
102 ' "$f1" "-" > "$f3"
103
104 case "${format}" in
105 "json")
106 printf 'Status: 200 OK\r\n'
107 printf 'Content-Type: application/json; charset=utf-8\r\n\r\n'
108 sfeed_json < "$f3"
109 ;;
110 "html")
111 printf 'Status: 200 OK\r\n'
112 printf 'Content-Type: text/html; charset=utf-8\r\n\r\n'
113 sfeed_html < "$f3"
114 ;;
115 "twtxt")
116 printf 'Status: 200 OK\r\n'
117 printf 'Content-Type: text/plain; charset=utf-8\r\n\r\n'
118 sfeed_twtxt < "$f3"
119 ;;
120 "txt")
121 printf 'Status: 200 OK\r\n'
122 printf 'Content-Type: text/plain; charset=utf-8\r\n\r\n'
123 sfeed_plain < "$f3"
124 ;;
125 "xml")
126 printf 'Status: 200 OK\r\n'
127 printf 'Content-Type: text/xml; charset=utf-8\r\n\r\n'
128 sfeed_atom < "$f3"
129 ;;
130 *)
131 printf 'Status: 200 OK\r\n'
132 printf 'Content-Type: text/plain; charset=utf-8\r\n\r\n'
133 cat "$f3"
134 ;;
135 esac