Last active
December 4, 2022 12:36
-
-
Save Kirens/51e006f3a868a4a01fce43535474f789 to your computer and use it in GitHub Desktop.
TVmannen 2.0. Skynet version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE OverloadedStrings #-} | |
import qualified Data.ByteString.Lazy as BL | |
import qualified Data.Text as T | |
import qualified Data.Text.Encoding as TE | |
import qualified Network.Wai as Wai | |
import qualified Network.Wai.Handler.Warp as Warp | |
import qualified Network.Wai.Middleware.RequestLogger as RequestLogger | |
import qualified Network.Wai.Middleware.Static as Static | |
import qualified Network.Wai.Parse as Parse | |
import qualified System.Directory as Directory | |
import qualified System.FilePath as FilePath | |
-- | The API token for authenticating requests. | |
apiToken :: T.Text | |
apiToken = "YOUR_API_TOKEN_HERE" | |
-- | The list of allowed file extensions for images and videos. | |
allowedExtensions :: [T.Text] | |
allowedExtensions = ["jpg", "jpeg", "png", "mp4"] | |
-- | The endpoint for uploading images and videos. | |
upload :: Wai.Application | |
upload request respond = do | |
-- Get the API token from the request headers. | |
let maybeApiToken = lookup "Authorization" (Wai.requestHeaders request) | |
-- Check if the API token is provided and valid. | |
if maybeApiToken /= Just (TE.encodeUtf8 apiToken) | |
-- Return an error if the API token is not provided or is invalid. | |
then respond (Wai.responseLBS Wai.status401 [] "Unauthorized") | |
else do | |
-- Parse the request body to get the uploaded file. | |
(params, _) <- Parse.parseRequestBody Parse.lbsBackEnd request | |
-- Check if a file was uploaded. | |
case lookup "media" params of | |
-- Return an error if no file was uploaded. | |
Nothing -> respond (Wai.responseLBS Wai.status400 [] "No file was uploaded") | |
-- Continue if a file was uploaded. | |
Just file -> do | |
-- Get the file name and extension from the uploaded file. | |
let fileName = TE.decodeUtf8 (Parse.fileName file) | |
fileExtension = T.toLower (T.takeWhileEnd (/= '.') fileName) | |
-- Check if the file extension is allowed. | |
if fileExtension `elem` allowedExtensions | |
-- Continue if the file extension is allowed. | |
then do | |
-- Save the uploaded file to the "media" directory. | |
let filePath = FilePath.joinPath ["media", fileName] | |
BL.writeFile filePath (Parse.fileContent file) | |
-- Return the URL of the uploaded file. | |
let url = T.concat ["https://your-image-hosting-service.com/media/", fileName] | |
respond (Wai.responseLBS Wai.status200 [] (TE.encodeUtf8 url)) | |
-- Delete the uploaded file and return an error if the file extension is not allowed. | |
else do | |
Directory.removeFile (Parse.fileContent file) | |
respond (Wai.responseLBS Wai.status400 [] "Only images and videos are allowed") | |
-- | The endpoint for listing all available media. | |
media :: Wai.Application | |
media request respond = do | |
-- Get the API token from the request headers. | |
let maybeApiToken = lookup "Authorization" (Wai.requestHeaders request) | |
-- Check if the API token is provided and valid. | |
if maybeApiToken /= Just (TE.encodeUtf8 apiToken) | |
-- Return an error if the API token is not provided or is invalid. | |
then respond (Wai.responseLBS Wai.status401 [] "Unauthorized") | |
else do | |
-- Get a list of all files in the "media" directory. | |
files <- Directory.listDirectory "media" | |
-- Return a list of URLs for all available media. | |
let media = map (\file -> T.concat ["https://your-image-hosting-service.com/media/", T.pack file]) files | |
respond (Wai.responseLBS Wai.status200 [] (TE.encodeUtf8 (show media))) | |
-- | The main entry point for the application. | |
main :: IO () | |
main = do | |
-- Set up the middleware for logging requests and serving static files. | |
let app = RequestLogger.logStdout (Static.staticPolicy (Static.addBase "media")) | |
-- Set up the server. | |
Warp.run 3000 app | |
-- | The top-level application that routes requests to the appropriate endpoint. | |
app :: Wai.Application | |
app request respond = | |
case (Wai.requestMethod request, Wai.pathInfo request) of | |
-- Handle the "POST /upload" request by calling the "upload" endpoint. | |
("POST", ["upload"]) -> upload request respond | |
-- Handle the "GET /media" request by calling the "media" endpoint. | |
("GET", ["media"]) -> media request respond | |
-- Handle all other requests by returning a "404 Not Found" response. | |
_ -> respond (Wai.responseLBS Wai.status404 [] "Not Found") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const express = require('express'); | |
const multer = require('multer'); | |
const fs = require('fs'); | |
// Set up express app | |
const app = express(); | |
// Set up file upload middleware | |
const upload = multer({ dest: 'uploads/' }); | |
// Set up API token | |
const API_TOKEN = 'YOUR_API_TOKEN_HERE'; | |
// Set up endpoint for uploading images and videos | |
app.post('/upload', upload.single('media'), (req, res) => { | |
if (!req.headers.authorization || req.headers.authorization !== API_TOKEN) { | |
// Return error if API token is not provided or is invalid | |
return res.status(401).json({ error: 'Unauthorized' }); | |
} | |
// Get the file that was uploaded | |
const file = req.file; | |
if (!file) { | |
// Return error if no file was uploaded | |
return res.status(400).json({ error: 'No file was uploaded' }); | |
} | |
// Get the file extension | |
const fileExtension = file.originalname.split('.').pop(); | |
// Check if the file is an image or video | |
if (fileExtension !== 'jpg' && fileExtension !== 'jpeg' && fileExtension !== 'png' && fileExtension !== 'mp4') { | |
// Delete the uploaded file if it is not an image or video | |
fs.unlinkSync(file.path); | |
// Return error if the file is not an image or video | |
return res.status(400).json({ error: 'Only images and videos are allowed' }); | |
} | |
// Move the file to a permanent location | |
fs.renameSync(file.path, `media/${file.filename}.${fileExtension}`); | |
// Return the URL of the uploaded media | |
res.json({ url: `https://your-image-hosting-service.com/media/${file.filename}.${fileExtension}` }); | |
}); | |
// Set up endpoint for listing all available media | |
app.get('/media', (req, res) => { | |
if (!req.headers.authorization || req.headers.authorization !== API_TOKEN) { | |
// Return error if API token is not provided or is invalid | |
return res.status(401).json({ error: 'Unauthorized' }); | |
} | |
// Get a list of all files in the media directory | |
const files = fs.readdirSync('media/'); | |
// Return a list of URLs for all available media | |
res.json({ | |
media: files.map(file => `https://your-image-hosting-service.com/media/${file}`) | |
}); | |
}); | |
// Start the server | |
const PORT = process.env.PORT || 3000; | |
app.listen(PORT, () => { | |
console.log(`Server is listening on port ${PORT}`); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Set up imports. | |
import Browser | |
import Html exposing (Html, img, video, text) | |
import Html.Attributes exposing (src, autoplay, loop) | |
import Html.Events exposing (onEnd) | |
import Json.Decode as Decode | |
import Time exposing (Time, every) | |
-- MODEL | |
-- The interval between switching to the next media (in milliseconds). | |
interval : Time | |
interval = 5 * 1000 | |
-- The current index of the media to show. | |
type alias Model = | |
{ index : Int } | |
-- The initial model. | |
init : (Model, Cmd Msg) | |
init = | |
( Model 0, Cmd.none ) | |
-- UPDATE | |
-- The possible messages for updating the model. | |
type Msg | |
= Next | |
| Media (List String) | |
-- Update the model by applying the given message. | |
update : Msg -> Model -> (Model, Cmd Msg) | |
update msg model = | |
case msg of | |
-- Increment the current index and start the interval. | |
Next -> | |
( Model ( (model.index + 1) % List.length model.media ), startInterval ) | |
-- Set the list of media and start the interval. | |
Media media -> | |
( Model 0, startInterval ) | |
-- Start the interval for switching to the next media. | |
startInterval : Cmd Msg | |
startInterval = | |
every interval Next | |
-- VIEW | |
-- The view for rendering the current media. | |
view : Model -> Html Msg | |
view model = | |
case model.media of | |
-- Show a message if no media is available. | |
[] -> | |
text "No media available" | |
-- Show the current media. | |
media -> | |
let | |
-- Get the URL of the current media. | |
url = | |
List.get model.index media | |
-- Check if the current media is an image. | |
isImage = | |
String.endsWith ".jpg" url || String.endsWith ".jpeg" url || String.endsWith ".png" url | |
in | |
-- Show the current media. | |
if isImage then | |
img [ src url ] [] | |
else | |
video [ src url, autoplay True, loop True, onEnd Next ] [] | |
-- SUBSCRIPTIONS | |
-- The subscriptions for updating the model. | |
subscriptions : Model -> Sub Msg | |
subscriptions model = | |
Sub.none | |
-- MAIN | |
-- The main entry point for the application. | |
main : Program () Model Msg | |
main = | |
Browser.sandbox | |
{ init = init | |
, update = update | |
, view = view | |
, subscriptions = subscriptions | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Image Carousel</title> | |
<style> | |
/* Fullscreen styles */ | |
html, body { | |
margin: 0; | |
padding: 0; | |
width: 100%; | |
height: 100%; | |
} | |
/* Image and video styles */ | |
img, video { | |
max-width: 100%; | |
max-height: 100%; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="carousel"> | |
<!-- Placeholder for carousel items --> | |
</div> | |
<script> | |
// Set up carousel interval | |
const INTERVAL = 5000; // 5 seconds | |
// Set up API endpoint | |
const API_ENDPOINT = 'https://your-image-hosting-service.com/media'; | |
// Set up API token | |
const API_TOKEN = 'YOUR_API_TOKEN_HERE'; | |
// Set up carousel element | |
const carousel = document.getElementById('carousel'); | |
// Set up current index | |
let currentIndex = 0; | |
// Set up carousel items | |
let items = []; | |
// Set up carousel interval | |
let interval = null; | |
// Fetch media from API | |
const fetchMedia = async () => { | |
try { | |
// Send request to API endpoint | |
const response = await fetch(API_ENDPOINT, { | |
headers: { | |
authorization: API_TOKEN | |
} | |
}); | |
// Parse response as JSON | |
const data = await response.json(); | |
// Set items to the list of media URLs | |
items = data.media; | |
// Start the carousel | |
startCarousel(); | |
} catch (error) { | |
// Log error to the console | |
console.error(error); | |
} | |
}; | |
// Start the carousel | |
const startCarousel = () => { | |
// Clear existing interval | |
clearInterval(interval); | |
// Set up the first carousel item | |
setCarouselItem(currentIndex); | |
// Set up the carousel interval | |
interval = setInterval(() => { | |
// Increment the current index | |
currentIndex = (currentIndex + 1) % items.length; | |
// Set up the next carousel item | |
setCarouselItem(currentIndex); | |
}, INTERVAL); | |
}; | |
// Set up the carousel item at the given index | |
const setCarouselItem = index => { | |
// Get the URL of the media at the given index | |
const url = items[index]; | |
// Check if the URL points to an image or a video | |
if (url.endsWith('.jpg') || url.endsWith('.jpeg') || url.endsWith('.png')) { | |
// Create an image element | |
const img = document.createElement('img'); | |
// Set the src attribute of the image element | |
img.setAttribute('src', url); | |
// Set the image as the carousel item | |
carousel.innerHTML = ''; | |
carousel.appendChild(img); | |
} else if (url.endsWith('.mp4')) { | |
// Create a video element | |
const video = document.createElement('video'); | |
// Set the src attribute of the video element | |
video.setAttribute('src', url); | |
// Set the video to play automatically | |
video.setAttribute('autoplay', true); | |
// Set the video to loop | |
video.setAttribute('loop', true); | |
// Set the video as the carousel item | |
carousel.innerHTML = ''; | |
carousel.appendChild(video); | |
// Listen for the "ended" event on the video element | |
video.addEventListener('ended', () => { | |
// Increment the current index | |
currentIndex = (currentIndex + 1) % items.length; | |
// Set up the next carousel item | |
setCarouselItem(currentIndex); | |
}); | |
} | |
}; | |
// Fetch media from the API and start the carousel | |
fetchMedia(); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Base | |
Write me a node.js script for an image and video hosting service that delivers media to a website's image carousel. The uploading needs to be protected by an API token | |
The api also need to provide an endpoint to list all available media | |
Great! Now write me a frontend that is simply showing one image at a time in fullscreen and rotating between them. The videos should ignore the regular interval and switch when it is done playing. | |
Keep going where you left of | |
# Branch 1 | |
Rewrite the backend in Haskell | |
continue where you left off | |
continue | |
Rewrite the frontend in Elm | |
Note what? | |
# Branch 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=== Base | |
Sure, here is a node.js script for an image and video hosting service that delivers media to a website's image carousel. The uploading will be protected by an API token. | |
In this script, we use the express and multer packages to set up an endpoint for uploading images and videos. The endpoint uses the API_TOKEN for authentication, and only accepts files with the jpg, jpeg, png, or mp4 extensions. The uploaded files are stored in the media directory, and the URL of the uploaded file is returned in the response. | |
Note: This script is for demonstration purposes only and may need to be adapted for your specific use case. | |
--- | |
Sure, here is an updated version of the script that includes an endpoint for listing all available media. | |
In this updated script, we added an /media endpoint that lists all available media. This endpoint also uses the API_TOKEN for authentication, and returns a list of URLs for all the files in the media directory | |
--- | |
Sure, here is an HTML page that shows one image or video at a time in fullscreen and rotates between them. The videos will be ignored by the regular interval and will switch to the next media when they are done playing. | |
--- | |
Sure, here is the continuation of the HTML page that shows one image or video at a time in fullscreen and rotates between them. The videos will be ignored by the regular interval and will switch to the next media when they are done playing. | |
In this updated HTML page, we added a script that fetches a list of media URLs from an API and sets up the carousel to show each media in turn. The script also handles videos by listening for the ended event and switching to the next media when the video is done playing. | |
Note: This HTML page is for demonstration purposes only and may need to be adapted for your specific use case. | |
=== Branch 1 | |
Sure, here is a Haskell script for an image and video hosting service that delivers media to a website's image carousel. The uploading will be protected by an API token. | |
--- | |
Sure, here is the continuation of the Haskell script for an image and video hosting service that delivers media to a website's image carousel. The uploading will be protected by an API token. | |
--- | |
Sure, here is the continuation of the Haskell script for an image and video hosting service that delivers media to a website's image carousel. The uploading will be protected by an API token. | |
In this updated Haskell script, we added an media endpoint that lists all available media. This endpoint also uses the apiToken for authentication, and returns a list of URLs for all the files in the media directory. | |
Note: This Haskell script is for demonstration purposes only and may need to be adapted for your specific use case. | |
--- | |
Sure, here is an Elm page that shows one image or video at a time in fullscreen and rotates between them. The videos will be ignored by the regular interval and will switch to the next media when they are done playing. | |
In this Elm page, we defined a Model that contains the current index of the media to show, and an update function that increments the index and starts an interval for switching to the next media. The view function then uses the current index and list of media to render the appropriate image or video, and listens for the ended event on videos to switch to the next media when the video is done playing. | |
Note: | |
--- | |
Note that this Elm page is for demonstration purposes only and may need to be adapted for your specific use case. It does not include any code for fetching the list of media URLs from the API. You can add this functionality by using the Http.send function to make a GET request to the /media endpoint and decode the response using the Json.Decode.list function. You can then pass the list of media URLs to the update function using a Media message. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment