]> OzVa Git service - shopping-channel/commitdiff
Started implementing twitch extension
authorMax Value <greenwoodw50@gmail.com>
Mon, 7 Apr 2025 22:43:23 +0000 (23:43 +0100)
committerMax Value <greenwoodw50@gmail.com>
Mon, 7 Apr 2025 22:43:23 +0000 (23:43 +0100)
extensions/config.html [new file with mode: 0644]
extensions/pricing.html [new file with mode: 0644]
extensions/product.html [new file with mode: 0644]
media/products/0.png [new file with mode: 0644]
media/products/1.png [new file with mode: 0644]
media/products/hold.png [new file with mode: 0644]
teleshopping.py

diff --git a/extensions/config.html b/extensions/config.html
new file mode 100644 (file)
index 0000000..738b093
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8">
+               <title>XMDV</title>
+               <style>
+               </style>
+               <script src="https://extension-files.twitch.tv/helper/v1/twitch-ext.min.js"></script>
+       </head>
+       <body>
+               <h1><a href="https://shopping.ozva.co.uk/admin">. Admin panel</a></h1>
+       </body>
+</html>
diff --git a/extensions/pricing.html b/extensions/pricing.html
new file mode 100644 (file)
index 0000000..8404bfd
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8">
+               <title>XMDV</title>
+               <style>
+               </style>
+               <script src="https://extension-files.twitch.tv/helper/v1/twitch-ext.min.js"></script>
+       </head>
+       <body>
+               <h1>This is some text</h1>
+               <h2>You are accesing the pricing version of this document.</h2>
+       </body>
+</html>
diff --git a/extensions/product.html b/extensions/product.html
new file mode 100644 (file)
index 0000000..75eebae
--- /dev/null
@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <meta charset="utf-8">
+               <title>XMDV</title>
+               <style>
+body {
+       overflow: hidden;
+       background-color: black;
+}
+
+@keyframes spin {
+    0% {transform: perspective(200px) translate(-50%, -50%) rotateY( 15deg ) rotateZ(0turn) scale(1.2);}
+    25% {transform: perspective(250px) translate(-50%, -50%) rotateY( 15deg ) rotateZ(0.25turn) scale(1);}
+    50% {transform: perspective(300px) translate(-50%, -50%) rotateY( 15deg ) rotateZ(0.5turn) scale(1.2);}
+    75% {transform: perspective(250px) translate(-50%, -50%) rotateY( 15deg ) rotateZ(0.75turn) scale(1);}
+    100% {transform: perspective(200px) translate(-50%, -50%) rotateY( 15deg ) rotateZ(1turn) scale(1.2);}
+}
+@keyframes text {
+    0% {transform: perspective(500px) rotateY( -10deg ) rotateZ(-0.01turn);}
+    50% {transform: perspective(500px) rotateY( -10deg) rotateZ(0.01turn);}
+    100% {transform: perspective(500px) rotateY( -10deg ) rotateZ(-0.01turn);}
+}
+
+#image {
+       position: absolute;
+       top: 50vh;
+       left: 50vw;
+       transform: translate(-50%,-50%);
+       opacity: 1;
+       transition: opacity 3s;
+}
+#image.hide {
+       opacity: 0;
+}
+#nameContainer {
+       position: absolute;
+       bottom: 25vh;
+       left: 25vh;
+}
+#nameTextContainer {
+       position: absolute;
+       bottom: -22vh;
+       left: -25vh;
+       width: 100vw;
+       color: white;
+       text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
+       font-family: sans-serif;
+       font-size: 5vw;
+       line-height: 10vw;
+       text-align: left;
+       transform: translateX(0);
+       opacity: 1;
+    transition: transform 3s, opacity 3s;
+}
+#name {
+    animation: text 10s linear 0s infinite;
+}
+#nameBadgeContainer {
+       position: absolute;
+       top: 0;
+       left: 0;
+       transform: translateY(0);
+       opacity: 1;
+    transition: transform 3s, opacity 3s;
+}
+#nameBadgeContainer > img {
+       width: 32vw;
+       height: 32vw;
+    animation: spin 10s linear 0s infinite;
+}
+
+#nameContainer.hide > #nameBadgeContainer {
+       transform: translateY(calc(25vh + 16vw));
+       opacity: 0;
+}
+#nameContainer.hide > #nameTextContainer {
+       transform: translateX(30vw);
+       opacity: 0;
+}
+
+@media (orientation: portrait) {
+       #image {
+               height: 100vh;
+       }
+}
+@media (orientation: landscape) {
+       #image {
+               height: 100vw;
+       }
+}
+
+               </style>
+               <script src="https://extension-files.twitch.tv/helper/v1/twitch-ext.min.js"></script>
+       </head>
+       <body onload="setInterval(update, 20000);">
+               <img id="image" src="https://shopping.ozva.co.uk/api/img/hold"></img>
+               <div id="nameContainer" class="hide">
+            <div id="nameBadgeContainer">
+                <img src="https://shopping.ozva.co.uk/static/assets/star5.svg"></img>
+            </div>
+            <div id="nameTextContainer">
+                <h1 id="name" style="top: 0">Product Name!</h1>
+            </div>
+               </div>
+
+               <script>
+
+let pastId = 0;
+
+function update() {
+
+       // setup and hide the name element & the image element
+       const name = document.getElementById("nameContainer");
+       const image = document.getElementById("image");
+       name.classList.add("hide")
+
+       fetch("https://shopping.ozva.co.uk/api/items", {cache: "default"})
+    .then(data => data.json())
+    .then(dataStatic => {
+        fetch("https://shopping.ozva.co.uk/api", {cache: "no-store"})
+        .then(data => data.json())
+        .then(data => {
+
+            // some variable setup
+            let id = data.item_id;
+            const items = dataStatic.items
+            const item = items[id];
+
+                       // hide the image if the item has changed
+                       if (id != pastId) { image.classList.add("hide"); }
+
+                       // change the image if the item has changed as soon as ftb
+                       if (id != pastId) {
+                               setTimeout(function () {
+                                       image.src = `https://shopping.ozva.co.uk/api/img/${id}`;
+                               }, 3000);
+                       }
+
+
+                       // regester the function to update the name and show the badge
+                       setTimeout(function () {
+                               document.getElementById("name").innerHTML = item.subtext;
+
+                               pastId = id;
+
+                               image.classList.remove("hide");
+                               name.classList.remove("hide");
+                       }, 10000);
+               });
+       });
+}
+
+               </script>
+       </body>
+</html>
diff --git a/media/products/0.png b/media/products/0.png
new file mode 100644 (file)
index 0000000..06e2a05
Binary files /dev/null and b/media/products/0.png differ
diff --git a/media/products/1.png b/media/products/1.png
new file mode 100644 (file)
index 0000000..3c4e251
Binary files /dev/null and b/media/products/1.png differ
diff --git a/media/products/hold.png b/media/products/hold.png
new file mode 100644 (file)
index 0000000..06e2a05
Binary files /dev/null and b/media/products/hold.png differ
index cd4b51f5987f9a055507220027e975497d5c92f3..04574efbe9c37c2868dd32dd7a06f9b644317db4 100755 (executable)
@@ -73,6 +73,13 @@ def sounds_page():
 
 
 
+@app.route("/extensions/<string:filename>")
+def interface_page(filename):
+       return send_from_directory("extensions", filename)
+
+
+
+
 @app.route("/docs")
 @auth.login_required
 def web_docs():
@@ -196,6 +203,10 @@ def api_clock():
        else:
                return "", 404
 
+@app.route("/api/img/<int:item_id>")
+def product_image(item_id):
+       return send_from_directory(path.join("media", "products"), f"{item_id}.png")
+
 @app.route("/api/generate")
 @auth.login_required
 def generate_docs():