summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolpeon <git@volpeon.ink>2021-03-10 19:27:04 +0100
committerVolpeon <git@volpeon.ink>2021-03-10 19:27:04 +0100
commit61d37c1ed5818e7f5d53f358495e5349ae817702 (patch)
tree4f289beaed9386203204c28f142b6726721012c2
downloadlivestream-irc-61d37c1ed5818e7f5d53f358495e5349ae817702.tar.gz
livestream-irc-61d37c1ed5818e7f5d53f358495e5349ae817702.tar.bz2
livestream-irc-61d37c1ed5818e7f5d53f358495e5349ae817702.zip
Init
-rw-r--r--index.html71
-rw-r--r--robots.txt2
-rw-r--r--script.js69
-rw-r--r--style.css224
4 files changed, 366 insertions, 0 deletions
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..01e48f8
--- /dev/null
+++ b/index.html
@@ -0,0 +1,71 @@
1<!DOCTYPE html>
2<html lang="en">
3
4<head>
5 <meta charset="utf-8" />
6 <meta name="viewport" content="width=device-width, initial-scale=1" />
7 <meta name="robots" content="noindex" />
8
9 <title>Livestream IRC</title>
10
11 <link rel="stylesheet" href="style.css" />
12</head>
13
14<body>
15 <section class="c-section c-section--create">
16 <form class="c-form" action="index.html" method="GET">
17 <label class="c-form-field">
18 <div class="c-form-field__label">Title</div>
19 <input class="c-form-field__input" name="title" />
20 <div class="c-form-field__help">
21 Optional title for your stream page.
22 </div>
23 </label>
24 <label class="c-form-field">
25 <div class="c-form-field__label">Stream embed URL</div>
26 <input class="c-form-field__input" name="stream" />
27 <div class="c-form-field__help">
28 The URL of the stream you want to embed.
29 Make sure you use an embed URL so only the player is displayed instead of the whole website.
30 In case of PeerTube, replace the "/watch/" part in the URL with "/embed/".
31 </div>
32 </label>
33 <label class="c-form-field">
34 <div class="c-form-field__label">IRC channel URL</div>
35 <input class="c-form-field__input" name="irc" />
36 <div class="c-form-field__help">
37 The URL pointing to a channel on an IRC server.
38 It has the format "ircs://chat.server/channel", where "chat.server" is the IRC server
39 and "channel" the name of the channel without the leading #.
40 Use "irc://..." if the server does not support TLS.
41 </div>
42 </label>
43 <button class="c-form-field">Create</button>
44 </form>
45 </section>
46
47 <section class="c-section c-section--main u-hidden">
48 <div class="c-msg">
49 <p class="c-msg__content">
50 <a class="c-irc-link" href="ircs://irc.vulpes.one:6697/livestream">Join #livestream on irc.vulpes.one</a>
51 </p>
52 <button class="c-msg__close">
53 <div class="c-close-icon"></div>
54 </button>
55 </div>
56
57 <div class="c-frame c-frame--pt">
58 <iframe width="560" height="315" sandbox="allow-same-origin allow-scripts allow-popups" frameborder="0"
59 allowfullscreen></iframe>
60 </div>
61
62 <div class="c-frame c-frame--irc">
63 <iframe width="560" height="315" sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
64 frameborder="0"></iframe>
65 </div>
66 </section>
67
68 <script type=text/javascript src="script.js"></script>
69</body>
70
71</html>
diff --git a/robots.txt b/robots.txt
new file mode 100644
index 0000000..1f53798
--- /dev/null
+++ b/robots.txt
@@ -0,0 +1,2 @@
1User-agent: *
2Disallow: /
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..e2c8f36
--- /dev/null
+++ b/script.js
@@ -0,0 +1,69 @@
1(() => {
2 const queryString = window.location.search;
3 const urlParams = new URLSearchParams(queryString);
4
5 const title = urlParams.get("title");
6 const streamUrl = urlParams.get("stream");
7 const ircUrl = urlParams.get("irc");
8
9 if (streamUrl === null || ircUrl === null) {
10 return;
11 }
12
13 /** @type HTMLInputElement */
14 const titleEl = document.querySelector(".c-form-field__input[name=title]");
15 /** @type HTMLInputElement */
16 const streamEl = document.querySelector(".c-form-field__input[name=stream]");
17 /** @type HTMLInputElement */
18 const ircEl = document.querySelector(".c-form-field__input[name=irc]");
19
20 titleEl.value = title;
21 streamEl.value = streamUrl;
22 ircEl.value = ircUrl;
23
24 if (streamUrl.trim().length === 0 || ircUrl.trim().length === 0) {
25 return;
26 }
27
28 const normalizedircUrl = ircUrl.startsWith("irc://")
29 ? ircUrl.substring(6)
30 : ircUrl.startsWith("ircs://")
31 ? ircUrl.substring(7)
32 : ircUrl;
33 const ircUrlComponents = normalizedircUrl.split("/");
34
35 if (ircUrlComponents.length !== 2) {
36 return;
37 }
38
39 if (title !== null && title.trim().length !== 0) {
40 document.querySelector("title").textContent = title;
41 }
42
43 const ircChan = ircUrlComponents[0];
44 const ircHost = ircUrlComponents[1];
45
46 document.querySelector(".c-section--create").classList.add("u-hidden");
47 document.querySelector(".c-section--main").classList.remove("u-hidden");
48
49 /** @type HTMLIFrameElement */
50 const streamFrameEl = document.querySelector(".c-frame--pt iframe");
51 /** @type HTMLIFrameElement */
52 const ircFrameEl = document.querySelector(".c-frame--irc iframe");
53
54 streamFrameEl.src = streamUrl;
55 ircFrameEl.src = "https://irc.vulpes.one/?uri=" + ircUrl;
56
57 /** @type HTMLAnchorElement */
58 const ircLink = document.querySelector(".c-irc-link");
59 ircLink.href = ircUrl;
60 ircLink.textContent = `Join #${ircChan} on ${ircHost}`;
61
62 document.querySelector(".c-msg__close").addEventListener("click", (e) => {
63 e.preventDefault();
64
65 /** @type HTMLElement */
66 const el = e.currentTarget;
67 el.parentElement.remove();
68 });
69})();
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..6be7ed3
--- /dev/null
+++ b/style.css
@@ -0,0 +1,224 @@
1
2
3:root {
4 --gray0: hsl(270, 0%, 7%);
5 --gray1: hsl(270, 0%, 10%);
6 --gray2: hsl(270, 1%, 16%);
7 --gray3: hsl(270, 1%, 24%);
8 --gray4: hsl(270, 1%, 35%);
9 --gray5: hsl(270, 2%, 54%);
10 --gray6: hsl(270, 2%, 73%);
11 --gray7: hsl(270, 2%, 100%);
12
13 /* * */
14
15 --bg-hi: var(--gray0);
16 --bg: var(--gray1);
17
18 --obj-hi: var(--gray2);
19 --obj: var(--gray3);
20 --obj-lo: var(--gray4);
21
22 --fg-hi: var(--gray5);
23 --fg: var(--gray6);
24 --fg-lo: var(--gray7);
25
26 /* * */
27
28 --color--yellow: hsl(38, 100%, 76%);
29}
30
31html {
32 height: 100%;
33}
34
35body {
36 height: 100%;
37 margin: 0;
38 font-family: IBM Plex Sans, -apple-system, system-ui, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, BlinkMacSystemFont, Helvetica Neue, Arial;
39 line-height: 1.5;
40 background-color: var(--bg);
41 color: var(--fg);
42}
43
44a {
45 text-decoration: none;
46}
47
48p {
49 margin: 0;
50}
51
52iframe {
53 display: block;
54 width: 100%;
55 height: 100%;
56}
57
58input {
59 padding: .5em .7em;
60 background: var(--obj);
61 color: var(--fg-lo);
62 border: 2px solid transparent;
63 border-radius: 3px;
64 transition: border-color .2s;
65}
66
67input:hover,
68input:focus {
69 border-color: var(--color--yellow);
70 box-shadow: none;
71 outline: 0;
72}
73
74button {
75 padding: .6em 1.3em;
76 font: inherit;
77 font-size: 12px;
78 font-weight: bold;
79 text-transform: uppercase;
80 letter-spacing: .2em;
81 background: transparent;
82 color: var(--color--yellow);
83 border: 2px solid var(--color--yellow);
84 border-radius: 3px;
85 transition: background-color .2s, color .2s;
86}
87
88button:hover,
89button:focus {
90 background-color: var(--color--yellow);
91 color: #000;
92}
93
94:link,
95:visited {
96 color: #850000;
97}
98
99.c-section {
100 height: 100%;
101}
102
103.c-section--main {
104 display: grid;