Initial commit
This commit is contained in:
		
						commit
						bcf3b8dd7f
					
				
							
								
								
									
										236
									
								
								index.n0m
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								index.n0m
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,236 @@
 | 
			
		||||
#!/usr/bin/env n0m
 | 
			
		||||
$ #!/bin/bash
 | 
			
		||||
Content-Type: text/html
 | 
			
		||||
 | 
			
		||||
# Constants
 | 
			
		||||
# =========
 | 
			
		||||
$ true=1;
 | 
			
		||||
$ false=0;
 | 
			
		||||
#
 | 
			
		||||
$ restaurant_file="restaurants.txt";
 | 
			
		||||
$ title="FeedMe";
 | 
			
		||||
#
 | 
			
		||||
# Components
 | 
			
		||||
# ==========
 | 
			
		||||
#
 | 
			
		||||
# $1: string: input value
 | 
			
		||||
# $2: number: 0=existing restaurant, 1=new restaurant
 | 
			
		||||
$ restaurant_form () {
 | 
			
		||||
$   enforce_arguments "${FUNCNAME[0]}" "$#" 2;
 | 
			
		||||
$   local icon_class;
 | 
			
		||||
$   if [ "$2" -eq 0 ]; then
 | 
			
		||||
$     icon_class="ri-save-2-fill";
 | 
			
		||||
$   else
 | 
			
		||||
$     icon_class="ri-add-line";
 | 
			
		||||
$   fi
 | 
			
		||||
    <form class="restaurant-form" method="POST" action="">
 | 
			
		||||
      <input type="hidden" name="old" value="<% $1 %>" />
 | 
			
		||||
      <input type="text" placeholder="Restaurant" name="new" value="<% $1 %>" />
 | 
			
		||||
      <label class="button <% $icon_class %>">
 | 
			
		||||
        $ local action;
 | 
			
		||||
        $ if [ "$2" -eq 0 ]; then
 | 
			
		||||
        $   action="save";
 | 
			
		||||
        $ else
 | 
			
		||||
        $   action="add";
 | 
			
		||||
        $ fi;
 | 
			
		||||
        <input type="submit" name="action" value="<% $action %>" />
 | 
			
		||||
      </label>
 | 
			
		||||
      $ if [ "$2" -eq 0 ]; then
 | 
			
		||||
        <label class="button ri-delete-bin-2-fill">
 | 
			
		||||
          <input type="submit" name="action" value="delete" />
 | 
			
		||||
        </label>
 | 
			
		||||
      $ fi
 | 
			
		||||
    </form>
 | 
			
		||||
$ }
 | 
			
		||||
#
 | 
			
		||||
# Utility Functions
 | 
			
		||||
# =================
 | 
			
		||||
#
 | 
			
		||||
# $1: string: function name
 | 
			
		||||
# $2: number: $#
 | 
			
		||||
# $3: number: expected number of arguments
 | 
			
		||||
$ enforce_arguments () {
 | 
			
		||||
$   if [ "$2" -lt "$3" ]; then
 | 
			
		||||
$     printf '%s %s %s\n' 'Function:' "$1" 'called with too few arguments';
 | 
			
		||||
$     exit 1;
 | 
			
		||||
$   elif [ "$2" -gt "$3" ]; then
 | 
			
		||||
$     printf '%s %s %s\n' 'Function:' "$1" 'called with too many arguments';
 | 
			
		||||
$     exit 1;
 | 
			
		||||
$   fi;
 | 
			
		||||
$ }
 | 
			
		||||
#
 | 
			
		||||
$ decode_uri () {
 | 
			
		||||
$   local i="${*//+/ }";
 | 
			
		||||
$   echo -e "${i//%/\\x}";
 | 
			
		||||
$ }
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# Restaurant List Functions
 | 
			
		||||
# =========================
 | 
			
		||||
#
 | 
			
		||||
# $1: string: restaurant to remove
 | 
			
		||||
$ remove_restaurant () {
 | 
			
		||||
$   enforce_arguments "${FUNCNAME[0]}" "$#" 1;
 | 
			
		||||
$   cat "$restaurant_file" | grep -Fxv "$1" | tee "$restaurant_file" >/dev/null;
 | 
			
		||||
$ }
 | 
			
		||||
#
 | 
			
		||||
# $1: string: restuarant to add
 | 
			
		||||
$ add_restaurant () {
 | 
			
		||||
$   enforce_arguments "${FUNCNAME[0]}" "$#" 1;
 | 
			
		||||
$   cat "$restaurant_file" |\
 | 
			
		||||
$     (grep -Fxv "$1"; printf '%s\n' "$1") |\
 | 
			
		||||
$     tee "$restaurant_file" >/dev/null;
 | 
			
		||||
$ }
 | 
			
		||||
#
 | 
			
		||||
# $1 (optional): number: 0=don't overwrite, 1=overwrite
 | 
			
		||||
$ todays_restaurant () {
 | 
			
		||||
$   local today="$(date +'%Y%m%d')";
 | 
			
		||||
$   local filename="$today.pick";
 | 
			
		||||
$   if [ -n "$1" ] && [ "$1" -ne 0 ]; then
 | 
			
		||||
$     rm "$filename";
 | 
			
		||||
$   fi;
 | 
			
		||||
$   if [ ! -f "$filename" ]; then
 | 
			
		||||
$     shuf -n 1 "$restaurant_file" > "$filename";
 | 
			
		||||
$   fi;
 | 
			
		||||
$   cat "$filename";
 | 
			
		||||
$ }
 | 
			
		||||
#
 | 
			
		||||
# Initialization
 | 
			
		||||
# ==============
 | 
			
		||||
#
 | 
			
		||||
# Make sure restaurant file eixsts
 | 
			
		||||
$ touch -a "$restaurant_file";
 | 
			
		||||
#
 | 
			
		||||
# Parse body
 | 
			
		||||
# ----------
 | 
			
		||||
$ declare -A body;
 | 
			
		||||
$ while IFS= read -d '&' -r pair || [ "$pair" ]; do
 | 
			
		||||
$   name=$(decode_uri "${pair%%=*}");
 | 
			
		||||
$   value=$(decode_uri "${pair#*=}");
 | 
			
		||||
$   if [ -n "$name" ]; then
 | 
			
		||||
$     body["$name"]="$value";
 | 
			
		||||
$   fi;
 | 
			
		||||
$ done #>
 | 
			
		||||
#
 | 
			
		||||
# Perform requested action
 | 
			
		||||
# ------------------------
 | 
			
		||||
$ case "${body['action']}" in
 | 
			
		||||
$   add)
 | 
			
		||||
$     add_restaurant "${body['new']}";
 | 
			
		||||
$     ;;
 | 
			
		||||
$   delete)
 | 
			
		||||
$     remove_restaurant "${body['old']}";
 | 
			
		||||
$     ;;
 | 
			
		||||
$   save)
 | 
			
		||||
$     remove_restaurant "${body['old']}";
 | 
			
		||||
$     add_restaurant "${body['new']}";
 | 
			
		||||
$     ;;
 | 
			
		||||
$   new_restaurant)
 | 
			
		||||
$     todays_restaurant $true >/dev/null;
 | 
			
		||||
$     ;;
 | 
			
		||||
$ esac
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
<!doctype html>
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <title><% $title %></title>
 | 
			
		||||
    <style>
 | 
			
		||||
      :root {
 | 
			
		||||
        --border-color: gray;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      html, body {
 | 
			
		||||
        margin: 0;
 | 
			
		||||
        padding: 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      html {
 | 
			
		||||
        font-family: sans-serif;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      body {
 | 
			
		||||
        background-color: #f5f5f5;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      \#title {
 | 
			
		||||
        color: rgba(0, 0, 0, 0.15);
 | 
			
		||||
        text-align: center;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      \#content {
 | 
			
		||||
        margin: 0 auto;
 | 
			
		||||
        width: fit-content;
 | 
			
		||||
        min-width: 400px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      \#todays-restaurant {
 | 
			
		||||
        text-align: center;
 | 
			
		||||
        font-size: 1.3em;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      \#restaurant-list {
 | 
			
		||||
        list-style-type: none;
 | 
			
		||||
        padding: 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .restaurant-form {
 | 
			
		||||
        display: flex;
 | 
			
		||||
      }
 | 
			
		||||
      .restaurant-form input[type='text'] {
 | 
			
		||||
        flex-grow: 1;
 | 
			
		||||
        border: 1px solid var(--border-color);
 | 
			
		||||
        padding: 0.4em 0.7em;
 | 
			
		||||
      }
 | 
			
		||||
      .restaurant-form label.button {
 | 
			
		||||
        border-radius: 0;
 | 
			
		||||
      }
 | 
			
		||||
      .restaurant-form > :not(:first-child) {
 | 
			
		||||
        border-left: 0;
 | 
			
		||||
      }
 | 
			
		||||
      \#restaurant-list > li:not(:last-child) .restaurant-form > * {
 | 
			
		||||
        border-bottom: 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      label.button {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        border: 1px solid var(--border-color);
 | 
			
		||||
        border-radius: 0.3em;
 | 
			
		||||
        padding: 0.2em 0.5em;
 | 
			
		||||
        background: #FDFDFD;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
      }
 | 
			
		||||
      label.button > span:first-of-type {
 | 
			
		||||
        flex-grow: 1;
 | 
			
		||||
        text-align: center;
 | 
			
		||||
      }
 | 
			
		||||
      label.button > input {
 | 
			
		||||
        display: none;
 | 
			
		||||
      }
 | 
			
		||||
    </style>
 | 
			
		||||
    <link
 | 
			
		||||
      href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css"
 | 
			
		||||
      rel="stylesheet"
 | 
			
		||||
    >
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <div id="content">
 | 
			
		||||
      <h1 id="title"><% $title %></h1>
 | 
			
		||||
      <p id="todays-restaurant">
 | 
			
		||||
        Today's Restaurant: <strong><$% todays_restaurant %></strong>
 | 
			
		||||
        <form method="POST" action="">
 | 
			
		||||
          <label class="button">
 | 
			
		||||
            <span>I want to go somewhere else</span>
 | 
			
		||||
            <input type="submit" name="action" value="new_restaurant" />
 | 
			
		||||
          </label>
 | 
			
		||||
        </form>
 | 
			
		||||
      </p>
 | 
			
		||||
      <ul id="restaurant-list">
 | 
			
		||||
        $ while IFS= read -r line || [ "$line" ]; do
 | 
			
		||||
          <li><$!% restaurant_form "$line" $false %></li>
 | 
			
		||||
        $ done <restaurants.txt #>
 | 
			
		||||
        <li><$!% restaurant_form "" $true %></li>
 | 
			
		||||
      </ul>
 | 
			
		||||
    </div>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user