~ekez/moonphase.is

6470f3deee50038ca3726359bfdb17a9faa2cbb8 — Zeke Medley 1 year, 3 months ago
Image and text showing current moon
7 files changed, 470 insertions(+), 0 deletions(-)

A .gitignore
A .prettierrc
A LICENSE
A README.md
A index.js
A package.json
A wrangler.toml
A  => .gitignore +10 -0
@@ 1,10 @@
/target
/dist
**/*.rs.bk
Cargo.lock
bin/
pkg/
wasm-pack.log
worker/
node_modules/
.cargo-ok

A  => .prettierrc +7 -0
@@ 1,7 @@
{
  "singleQuote": true,
  "semi": false,
  "trailingComma": "all",
  "tabWidth": 2,
  "printWidth": 80
}

A  => LICENSE +28 -0
@@ 1,28 @@
Copyright 2021 Zeke Medley

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file

A  => README.md +10 -0
@@ 1,10 @@
# moonphase

![An image of the moon from moonphase.is](https://moonphase.is/image.svg)

This is a simple webapp that shows a textual and visual representation
of the current phase of the moon. moonphase.is displays a textual
representation and moonphase.is/image.svg returns a different image
depending on the current phase of the moon.

The webapp is hosted on Cloudflare Workers.

A  => index.js +391 -0
@@ 1,391 @@
// Copyright 2021 Zeke Medley

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:

// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.

// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.

// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

const phases = ['new moon', 'waxing crescent', 'first quarter',
		'waxing gibbous', 'full moon', 'waning gibbous',
		'last quarter', 'waning crescent']

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})
/**
 * Respond with hello worker text
 * @param {Request} request
 */
async function handleRequest(request) {
    const theDate = new Date()

    const day = theDate.getDate()
    const month = theDate.getMonth() + 1 // For whatever reason this
					 // is in [0, 11]
    const year = theDate.getFullYear()

    const url = new URL(request.url)
    const path = url.pathname
    console.log(path)

    switch (path) {
    case '/':
	return new Response(calculatePhase(year, month, day), {
	    headers: { 'content-type': 'text/plain' },
	})
    case '/image.svg':
	const phase = calculatePhase(year, month, day)
	return new Response(images[phase], {
	    headers: { 'content-type': 'image/svg+xml'},
	})
    default:
	return new Response('404', { status: 404 })
	break
    }
}

// From: https://www.subsystems.us/uploads/9/8/9/4/98948044/moonphase.pdf
function calculatePhase(Y, M, D) {
    const A = Math.floor(Y / 100)
    const B = Math.floor(A / 4)
    const C = 2 - A + B
    const E = Math.floor(365.25 * (Y + 4716))
    const F = Math.floor(30.6001 * (M + 1))
    const JD = C + D + E + F - 1524.5

    const daysSinceNew = JD - 2451549.5
    const newMoons = daysSinceNew / 29.53

    const daysPerPhase = 3.69

    const daysIntoCycle = (newMoons - Math.floor(newMoons)) * 29.53
    const phaseIndex = Math.round(daysIntoCycle / daysPerPhase)
    const phase = phases[phaseIndex]

    return phase
}

const images = {
    'new moon': `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<!-- Created by Daniel Kmiec CC BY 3.0 -->
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.0"
   width="400"
   height="400"
   id="svg2">
  <defs
     id="defs4" />
  <g
     id="layer1">
    <rect
       width="400"
       height="400"
       x="0"
       y="-1.5454435e-014"
       style="fill:#0000bb;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="rect3239" />
  </g>
  <g
     id="layer2">
    <path
       d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1  411.67107,200.5305 A 168.70027 168.70027 0 1 1  749.07161 200.5305 z"
       transform="translate(-380.37134,-0.5305023)"
       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="path6166" />
  </g>
</svg>`,
    'waxing crescent': `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<!-- Created by Daniel Kmiec CC BY 3.0 -->
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.0"
   width="400"
   height="400"
   id="svg2">
  <defs
     id="defs4" />
  <g
     id="layer1">
    <rect
       width="400"
       height="400"
       x="0"
       y="-1.5454435e-014"
       style="fill:#0000bb;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="rect3239" />
  </g>
  <g
     id="layer2">
    <path
       d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1  411.67107,200.5305 A 168.70027 168.70027 0 1 1  749.07161 200.5305 z"
       transform="translate(-380.37134,-0.5305023)"
       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="path6166" />
  </g>
  <g
     id="layer3">
    <path
       d="M 199.862,368.70045 C 293.03269,368.70045 368.56242,293.17073 368.56242,200 C 368.56242,106.8293 293.03269,31.299555 199.862,31.299555 C 246.44791,31.299555 284.21221,106.8293 284.21221,200 C 284.21221,293.17073 246.44791,368.70045 199.862,368.70045 z "
       style="fill:#ffffff;fill-opacity:1;stroke:none"
       id="path7307" />
  </g>
</svg>
`,
    'first quarter': `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<!-- Created by Daniel Kmiec CC BY 3.0 -->
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.0"
   width="400"
   height="400"
   id="svg2">
  <defs
     id="defs4" />
  <g
     id="layer1">
    <rect
       width="400"
       height="400"
       x="0"
       y="-1.5454435e-014"
       style="fill:#0000bb;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="rect3239" />
  </g>
  <g
     id="layer2">
    <path
       d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1  411.67107,200.5305 A 168.70027 168.70027 0 1 1  749.07161 200.5305 z"
       transform="translate(-380.37134,-0.5305023)"
       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="path6166" />
  </g>
  <g
     id="layer3">
    <path
       d="M 199.86125,368.70045 C 292.83638,368.70045 368.20758,293.17071 368.20758,199.99995 C 368.20758,106.82922 292.83638,31.29945 199.86125,31.29945 C 199.12886,143.76656 199.72222,256.23321 199.86125,368.70045 z "
       style="fill:#ffffff;fill-opacity:1;stroke:none"
       id="path7307" />
  </g>
</svg>
`,
    'waxing gibbous': `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<!-- Created by Daniel Kmiec CC BY 3.0 -->
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.0"
   width="400"
   height="400"
   id="svg2">
  <defs
     id="defs4" />
  <g
     id="layer1">
    <rect
       width="400"
       height="400"
       x="0"
       y="-1.5454435e-014"
       style="fill:#0000bb;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="rect3239" />
  </g>
  <g
     id="layer2">
    <path
       d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1  411.67107,200.5305 A 168.70027 168.70027 0 1 1  749.07161 200.5305 z"
       transform="translate(-380.37134,-0.5305023)"
       style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="path6166" />
  </g>
  <g
     id="layer3">
    <path
       d="M 199.97697,368.70045 C 106.80628,368.70045 31.27656,293.17073 31.27656,200 C 31.27656,106.8293 106.80628,31.299555 199.97697,31.299555 C 153.39106,31.299555 115.62676,106.8293 115.62676,200 C 115.62676,293.17073 153.39106,368.70045 199.97697,368.70045 z "
       style="fill:#00000f;fill-opacity:0.94117647;stroke:none"
       id="path7307" />
  </g>
</svg>
`,
    'full moon': `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<!-- Created by Daniel Kmiec CC BY 3.0 -->
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.0"
   width="400"
   height="400"
   id="svg2">
  <defs
     id="defs4" />
  <g
     id="layer1">
    <rect
       width="400"
       height="400"
       x="0"
       y="-1.5454435e-014"
       style="fill:#0000bb;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="rect3239" />
  </g>
  <g
     id="layer2">
    <path
       d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1  411.67107,200.5305 A 168.70027 168.70027 0 1 1  749.07161 200.5305 z"
       transform="translate(-380.37134,-0.5305023)"
       style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="path6166" />
  </g>
  <g
     id="layer3" />
</svg>
`,
    'waning gibbous': `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<!-- Created by Daniel Kmiec CC BY 3.0 -->
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.0"
   width="400"
   height="400"
   id="svg2">
  <defs
     id="defs4" />
  <g
     id="layer1">
    <rect
       width="400"
       height="400"
       x="0"
       y="-1.5454435e-014"
       style="fill:#0000bb;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="rect3239" />
  </g>
  <g
     id="layer2">
    <path
       d="M 749.07161 200.5305 A 168.70027 168.70027 0 1 1  411.67107,200.5305 A 168.70027 168.70027 0 1 1  749.07161 200.5305 z"
       transform="translate(-380.37134,-0.5305023)"
       style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="path6166" />
  </g>
  <g
     id="layer3">
    <path
       d="M 200.0278,368.70045 C 293.19849,368.70045 368.72822,293.17073 368.72822,200 C 368.72822,106.8293 293.19849,31.299555 200.0278,31.299555 C 246.61371,31.299555 284.37801,106.8293 284.37801,200 C 284.37801,293.17073 246.61371,368.70045 200.0278,368.70045 z "
       style="fill:#00000f;fill-opacity:0.94117647;stroke:none"
       id="path7307" />
  </g>
</svg>
`,
    'last quarter': `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<!-- Created by Daniel Kmiec CC BY 3.0 -->
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.0"
   width="400"
   height="400"
   id="svg2">
  <defs
     id="defs4" />
  <g
     id="layer1">
    <rect
       width="400"
       height="400"
       x="0"
       y="-1.5454435e-014"
       style="fill:#0000bb;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="rect3239" />
  </g>
  <g
     id="layer2">
    <path
       d="M 749.07161,200.5305 C 749.07161,293.70109 673.54193,369.23077 580.37134,369.23077 C 487.20075,369.23077 411.67107,293.70109 411.67107,200.5305 C 411.67107,107.35991 487.20075,31.83023 580.37134,31.83023 C 673.54193,31.83023 749.07161,107.35991 749.07161,200.5305 z "
       transform="translate(-380.37134,-0.5305023)"
       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="path6166" />
  </g>
  <g
     transform="matrix(-1,0,0,1,399.50816,0)"
     id="layer3">
    <path
       d="M 199.86125,368.70045 C 292.83638,368.70045 368.20758,293.17071 368.20758,199.99995 C 368.20758,106.82922 292.83638,31.29945 199.86125,31.29945 C 199.12886,143.76656 199.72222,256.23321 199.86125,368.70045 z "
       style="fill:#ffffff;fill-opacity:1;stroke:none"
       id="path7307" />
  </g>
</svg>
`,
    'waning crescent': `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<!-- Created by Daniel Kmiec CC BY 3.0 -->
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.0"
   width="400"
   height="400"
   id="svg2">
  <defs
     id="defs4" />
  <g
     id="layer1">
    <rect
       width="400"
       height="400"
       x="0"
       y="-1.5454435e-014"
       style="fill:#0000bb;fill-opacity:1;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="rect3239" />
  </g>
  <g
     id="layer2">
    <path
       d="M 749.07161,200.5305 C 749.07161,293.70109 673.54193,369.23077 580.37134,369.23077 C 487.20075,369.23077 411.67107,293.70109 411.67107,200.5305 C 411.67107,107.35991 487.20075,31.83023 580.37134,31.83023 C 673.54193,31.83023 749.07161,107.35991 749.07161,200.5305 z "
       transform="translate(-380.37134,-0.5305023)"
       style="fill:#00000f;fill-opacity:0.94117647;stroke:none;stroke-width:3.54330707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
       id="path6166" />
  </g>
  <g
     id="layer3">
    <path
       d="M 199.97697,368.70045 C 106.80628,368.70045 31.27656,293.17073 31.27656,200 C 31.27656,106.8293 106.80628,31.299555 199.97697,31.299555 C 153.39106,31.299555 115.62676,106.8293 115.62676,200 C 115.62676,293.17073 153.39106,368.70045 199.97697,368.70045 z "
       style="fill:#ffffff;fill-opacity:1;stroke:none"
       id="path7307" />
  </g>
</svg>
`,
}

A  => package.json +16 -0
@@ 1,16 @@
{
  "private": true,
  "name": "moonphase",
  "version": "1.0.0",
  "description": "A template for kick starting a Cloudflare Workers project",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "format": "prettier --write '**/*.{js,css,json,md}'"
  },
  "author": "Zeke Medley <zekemedley@gmail.com>",
  "license": "MIT",
  "devDependencies": {
    "prettier": "^1.18.2"
  }
}

A  => wrangler.toml +8 -0
@@ 1,8 @@
name = "moonphase"
type = "javascript"

account_id = ""
workers_dev = true
route = ""
zone_id = ""
compatibility_date = "2021-10-13"