home to your local SPACEGIRL 💫 arimelody.space
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

the shrimplest admin api you've ever seen

Signed-off-by: ari melody <ari@arimelody.me>

+266 -12
+20
api/api.go
··· 1 + package api 2 + 3 + import ( 4 + "net/http" 5 + "html/template" 6 + 7 + "arimelody.me/arimelody.me/api/v1/admin" 8 + ) 9 + 10 + func Handle(writer http.ResponseWriter, req *http.Request, root *template.Template) int { 11 + code := 404; 12 + if req.URL.Path == "/api/v1/admin/login" { 13 + code = admin.HandleLogin(writer, req, root) 14 + } 15 + 16 + if code == 404 { 17 + writer.Write([]byte("404 not found")) 18 + } 19 + return code; 20 + }
+43
api/v1/admin/admin.go
··· 1 + package admin 2 + 3 + import ( 4 + "fmt" 5 + "html/template" 6 + "io" 7 + "net/http" 8 + ) 9 + 10 + type ( 11 + State struct { 12 + Token string 13 + } 14 + ) 15 + 16 + func CreateState() *State { 17 + return &State{ 18 + Token: "you are the WINRAR!!", 19 + } 20 + } 21 + 22 + func HandleLogin(writer http.ResponseWriter, req *http.Request, root *template.Template) int { 23 + if req.Method != "POST" { 24 + return 404; 25 + } 26 + 27 + body, err := io.ReadAll(req.Body) 28 + if err != nil { 29 + fmt.Printf("failed to parse request body!\n"); 30 + return 500; 31 + } 32 + 33 + if string(body) != "super epic mega gaming password" { 34 + return 400; 35 + } 36 + 37 + state := CreateState(); 38 + 39 + writer.WriteHeader(200); 40 + writer.Write([]byte(state.Token)) 41 + 42 + return 200; 43 + }
+31 -12
main.go
··· 1 1 package main 2 2 3 3 import ( 4 - "fmt" 5 - "html/template" 6 - "log" 7 - "net/http" 8 - "os" 9 - "strconv" 10 - "strings" 11 - "time" 4 + "fmt" 5 + "html/template" 6 + "log" 7 + "net/http" 8 + "os" 9 + "strconv" 10 + "strings" 11 + "time" 12 12 13 - "arimelody.me/arimelody.me/api/v1/music" 13 + "arimelody.me/arimelody.me/api" 14 + "arimelody.me/arimelody.me/api/v1/music" 14 15 15 - "github.com/gomarkdown/markdown" 16 - "github.com/gomarkdown/markdown/html" 17 - "github.com/gomarkdown/markdown/parser" 16 + "github.com/gomarkdown/markdown" 17 + "github.com/gomarkdown/markdown/html" 18 + "github.com/gomarkdown/markdown/parser" 18 19 ) 19 20 20 21 const PORT int = 8080 ··· 94 95 return music_gateway_handler(writer, req, root) 95 96 } 96 97 98 + if strings.HasPrefix(uri, "/admin") { 99 + return admin_handler(writer, req, root) 100 + } 101 + 102 + if strings.HasPrefix(uri, "/api") { 103 + return api.Handle(writer, req, root) 104 + } 105 + 97 106 return static_handler(writer, req, root) 98 107 }(writer, req) 99 108 ··· 131 140 } 132 141 gateway_template := template.Must(root.ParseFiles("views/music-gateway.html")) 133 142 err := gateway_template.Execute(writer, release) 143 + if err != nil { 144 + http.Error(writer, err.Error(), http.StatusInternalServerError) 145 + return 500 146 + } 147 + return 200 148 + } 149 + 150 + func admin_handler(writer http.ResponseWriter, req *http.Request, root *template.Template) int { 151 + admin_template := template.Must(root.ParseFiles("views/admin.html")) 152 + err := admin_template.Execute(writer, nil) 134 153 if err != nil { 135 154 http.Error(writer, err.Error(), http.StatusInternalServerError) 136 155 return 500
+152
public/style/admin.css
··· 1 + @import url("/style/main.css"); 2 + 3 + main { 4 + width: min(calc(100% - 4rem), 720px); 5 + min-height: calc(100vh - 10.3rem); 6 + margin: 0 auto 2rem auto; 7 + padding-top: 4rem; 8 + } 9 + 10 + main h1 { 11 + line-height: 3rem; 12 + color: var(--primary); 13 + } 14 + 15 + main h2 { 16 + color: var(--secondary); 17 + } 18 + 19 + main h3 { 20 + color: var(--tertiary); 21 + } 22 + 23 + div#me_irl { 24 + width: fit-content; 25 + height: fit-content; 26 + border: 2px solid white; 27 + } 28 + 29 + div#me_irl img { 30 + display: block; 31 + } 32 + 33 + div#me_irl::before { 34 + content: ""; 35 + position: absolute; 36 + width: 104px; 37 + height: 104px; 38 + transform: translate(2px, 2px); 39 + background-image: linear-gradient(to top right, 40 + var(--primary), 41 + var(--secondary)); 42 + z-index: -1; 43 + } 44 + 45 + h1, 46 + h2, 47 + h3, 48 + h4, 49 + h5, 50 + h6, 51 + p, 52 + small, 53 + blockquote { 54 + transition: background-color 0.1s; 55 + } 56 + 57 + h1 a, 58 + h2 a, 59 + h3 a, 60 + h4 a, 61 + h5 a, 62 + h6 a { 63 + color: inherit; 64 + } 65 + 66 + h1 a:hover, 67 + h2 a:hover, 68 + h3 a:hover, 69 + h4 a:hover, 70 + h5 a:hover, 71 + h6 a:hover { 72 + text-decoration: none; 73 + } 74 + 75 + main h1:hover, 76 + main h2:hover, 77 + main h3:hover, 78 + main h4:hover, 79 + main h5:hover, 80 + main h6:hover, 81 + main p:hover, 82 + main small:hover, 83 + main blockquote:hover { 84 + background-color: #fff1; 85 + } 86 + 87 + blockquote { 88 + margin: 1rem 0; 89 + padding: 0 2.5rem; 90 + } 91 + 92 + hr { 93 + text-align: center; 94 + line-height: 0px; 95 + border-width: 1px 0 0 0; 96 + border-color: #888f; 97 + margin: 1.5em 0; 98 + overflow: visible; 99 + } 100 + 101 + ul.links { 102 + display: flex; 103 + gap: 1em .5em; 104 + flex-wrap: wrap; 105 + } 106 + 107 + ul.links li { 108 + list-style: none; 109 + } 110 + 111 + ul.links li a { 112 + padding: .2em .5em; 113 + border: 1px solid var(--links); 114 + color: var(--links); 115 + border-radius: 2px; 116 + background-color: transparent; 117 + transition-property: color, border-color, background-color; 118 + transition-duration: .2s; 119 + animation-delay: 0s; 120 + animation: list-item-fadein .2s forwards; 121 + opacity: 0; 122 + } 123 + 124 + ul.links li a:hover { 125 + color: #eee; 126 + border-color: #eee; 127 + background-color: var(--links) !important; 128 + text-decoration: none; 129 + box-shadow: 0 0 1em var(--links); 130 + } 131 + 132 + div#web-buttons { 133 + margin: 2rem 0; 134 + } 135 + 136 + #web-buttons a { 137 + text-decoration: none; 138 + } 139 + 140 + #web-buttons img { 141 + image-rendering: auto; 142 + image-rendering: crisp-edges; 143 + image-rendering: pixelated; 144 + } 145 + 146 + #web-buttons img:hover { 147 + margin: -1px; 148 + border: 1px solid #eee; 149 + transform: translate(-2px, -2px); 150 + box-shadow: 1px 1px 0 #eee, 2px 2px 0 #eee; 151 + } 152 +
+20
views/admin.html
··· 1 + {{define "head"}} 2 + <title>admin - ari melody 💫</title> 3 + <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 + 5 + <link rel="stylesheet" href="/style/admin.css"> 6 + {{end}} 7 + 8 + {{define "content"}} 9 + <main> 10 + <script type="module" src="/script/admin.js" defer></script> 11 + 12 + <h1> 13 + # admin panel 14 + </h1> 15 + 16 + <p> 17 + bappity boopity 18 + </p> 19 + </main> 20 + {{end}}