Skip to content

Instantly share code, notes, and snippets.

@Kirens
Last active December 4, 2022 12:36
Show Gist options
  • Save Kirens/51e006f3a868a4a01fce43535474f789 to your computer and use it in GitHub Desktop.
Save Kirens/51e006f3a868a4a01fce43535474f789 to your computer and use it in GitHub Desktop.
TVmannen 2.0. Skynet version
{-# 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")
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}`);
});
-- 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
}
<!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>
# 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
=== 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