mirror of
				https://api.glitch.com/git/presence-button
				synced 2025-10-31 15:45:34 +00:00 
			
		
		
		
	🎺🌹 Checkpoint
./package.json:933874/26 ./server.js:933874/14940
This commit is contained in:
		
							parent
							
								
									8799fd4ed4
								
							
						
					
					
						commit
						b6194ba18d
					
				| @ -7,8 +7,7 @@ | ||||
|     "start": "node server.js" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "express": "^4.17.1", | ||||
|     "request": "^2.88.2" | ||||
|     "express": "^4.17.1" | ||||
|   }, | ||||
|   "engines": { | ||||
|     "node": "8.x" | ||||
|  | ||||
| @ -1,71 +0,0 @@ | ||||
| /* styles */ | ||||
| /* called by your view template */ | ||||
| 
 | ||||
| * { | ||||
|   box-sizing: border-box; | ||||
| } | ||||
| 
 | ||||
| body { | ||||
|   font-family: helvetica, arial, sans-serif; | ||||
|   margin: 2em; | ||||
| } | ||||
| 
 | ||||
| h1 { | ||||
|   font-style: italic; | ||||
|   color: #373fff; | ||||
| } | ||||
| 
 | ||||
| .bold { | ||||
|   font-weight: bold; | ||||
| } | ||||
| 
 | ||||
| p { | ||||
|   max-width: 600px; | ||||
| } | ||||
| 
 | ||||
| form { | ||||
|   margin-bottom: 25px; | ||||
|   padding: 15px; | ||||
|   background-color: cyan; | ||||
|   display: inline-block; | ||||
|   width: 100%; | ||||
|   max-width: 340px; | ||||
|   border-radius: 3px; | ||||
| } | ||||
| 
 | ||||
| input { | ||||
|   display: block; | ||||
|   margin-bottom: 10px; | ||||
|   padding: 5px; | ||||
|   width: 100%; | ||||
|   border: 1px solid lightgrey; | ||||
|   border-radius: 3px; | ||||
|   font-size: 16px; | ||||
| } | ||||
| 
 | ||||
| button { | ||||
|   font-size: 16px; | ||||
|   border-radius: 3px; | ||||
|   background-color: lightgrey; | ||||
|   border: 1px solid grey; | ||||
|   box-shadow: 2px 2px teal; | ||||
|   cursor: pointer; | ||||
| } | ||||
| 
 | ||||
| button:hover { | ||||
|   background-color: yellow; | ||||
| } | ||||
| 
 | ||||
| button:active { | ||||
|   box-shadow: none; | ||||
| } | ||||
| 
 | ||||
| li { | ||||
|   margin-bottom: 5px; | ||||
| } | ||||
| 
 | ||||
| footer { | ||||
|   margin-top: 50px; | ||||
|   padding-top: 25px; | ||||
|   border-top: 1px solid lightgrey; | ||||
| } | ||||
							
								
								
									
										244
									
								
								server.js
									
									
									
									
									
								
							
							
						
						
									
										244
									
								
								server.js
									
									
									
									
									
								
							| @ -1,240 +1,10 @@ | ||||
| const express = require("express"); | ||||
| const app = express(); | ||||
| const request = require("request"); | ||||
| const express = require("express") | ||||
| const app = express() | ||||
| 
 | ||||
| var fuzIsOpen = false; | ||||
| var lastSeen = new Date("1970-01-01"); | ||||
| var lastOpened = new Date("1970-01-01"); | ||||
| var lastClosed = new Date("1970-01-01"); | ||||
| 
 | ||||
| const fs = require("fs"); | ||||
| const path = require("path"); | ||||
| const db = "./.data/data.json"; | ||||
| const defaultClosingTimeout = 5 * 60 * 1000; // 5 mins
 | ||||
| 
 | ||||
| try { | ||||
|   fs.mkdirSync(path.dirname(db), { recursive: true }); | ||||
| } catch (err) {} | ||||
| try { | ||||
|   var content = fs.readFileSync(db, "utf8"); | ||||
|    | ||||
|   fuzIsOpen = JSON.parse(content)["fuzIsOpen"] || fuzIsOpen; | ||||
|   lastSeen = new Date(JSON.parse(content)["lastSeen"] || lastSeen); | ||||
|   lastOpened = new Date(JSON.parse(content)["lastOpened"] || lastOpened); | ||||
|   lastClosed = new Date(JSON.parse(content)["lastClosed"] || lastClosed); | ||||
| } catch (err) {console.log("err", err)} | ||||
| 
 | ||||
| app.use(express.static("public")); | ||||
| app.enable("trust proxy"); // needed for HTTP -> HTTPS redirect and successful test against req.secure
 | ||||
| 
 | ||||
| // redirect every route but /status as it's used by the ESP to send its status https://stackoverflow.com/a/49176816
 | ||||
| const redirectToHTTPS = (req, res, next) => { | ||||
|   if (req.secure) { | ||||
|     // request was via https, so do no special handling
 | ||||
|     next(); | ||||
|   } else { | ||||
|     // request was via http, so redirect to https
 | ||||
|     res.redirect("https://" + req.headers.host + req.originalUrl); | ||||
|   } | ||||
| }; | ||||
| app.use("/api", redirectToHTTPS); | ||||
| app.use("/img", redirectToHTTPS);                                                                                                                                                                                                                                               | ||||
|                                                                                                                                                                                                                                                                                 | ||||
| app.all("/", redirectToHTTPS); // no app.use here because it would match every path https://github.com/expressjs/express/issues/3260                                                                                                                                           
 | ||||
| app.get("/", (req, res) => {                                                                                                                                                                                                                                                    | ||||
|   res.sendFile(__dirname + "/views/index.html");                                                                                                                                                                                                                                | ||||
| });                                                                                                                                                                                                                                                                             | ||||
|                                                                                                                                                                                                                                                                                 | ||||
| app.get("/img", (req, res) => {                                                                                                                                                                                                                                                 | ||||
|   const closingTimeout = (typeof req.query.closingTimeout !== 'undefined')? req.query.closingTimeout : defaultClosingTimeout;                                                                                                                                                   | ||||
|   res.header(                                                                                                                                                                                                                                                                   | ||||
|     "Cache-Control",                                                                                                                                                                                                                                                            | ||||
|     "no-store, no-cache, must-revalidate, proxy-revalidate"                                                                                                                                                                                                                     | ||||
|   );                                                                                                                                                                                                                                                                            | ||||
|   res.header("Pragma", "no-cache");                                                                                                                                                                                                                                             | ||||
|   res.header("Expires", "0");                                                                                                                                                                                                                                                   | ||||
|   if (fuzIsOpen && new Date() - closingTimeout < lastSeen) {                                                                                                                                                                                                                    | ||||
|     // https://www.iconfinder.com/icons/1871431/online_open_shop_shopping_sign_icon                                                                                                                                                                                            
 | ||||
|     // formerly https://www.flaticon.com/free-icon/open_1234189, maybe try https://flaticons.net/customize.php?dir=Miscellaneous&icon=Open.png without attribution                                                                                                             
 | ||||
|     return res.sendFile(__dirname + "/views/open.svg");                                                                                                                                                                                                                         | ||||
|   }                                                                                                                                                                                                                                                                             | ||||
|   // https://www.iconfinder.com/icons/1871435/closed_online_shop_shopping_sign_icon                                                                                                                                                                                            
 | ||||
|   // formerly https://www.flaticon.com/free-icon/closed_1234190, maybe try https://flaticons.net/customize.php?dir=Miscellaneous&icon=Closed.png without attribution                                                                                                           
 | ||||
|   res.sendFile(__dirname + "/views/closed.svg");                                                                                                                                                                                                                                | ||||
| });                                                                                                                                                                                                                                                                             | ||||
|                                                                                                                                                                                                                                                                                 | ||||
| app.get("/api", (req, res) => {                                                                                                                                                                                                                                                 | ||||
|   res.header("Access-Control-Allow-Origin", "*");                                                                                                                                                                                                                               | ||||
|   res.header(                                                                                                                                                                                                                                                                   | ||||
|     "Access-Control-Allow-Headers",                                                                                                                                                                                                                                             | ||||
|     "Origin, X-Requested-With, Content-Type, Accept"                                                                                                                                                                                                                            | ||||
|   ); | ||||
|   res.header("Content-Type", "application/json"); | ||||
|   res.send( | ||||
|     JSON.stringify( | ||||
|       { | ||||
|         fuzIsOpen, | ||||
|         lastSeen, | ||||
|         lastOpened, | ||||
|         lastClosed, | ||||
|         processUptime: formatSeconds(process.uptime()) | ||||
|       }, | ||||
|       null, | ||||
|       4 | ||||
|     ) | ||||
|   ); | ||||
| }); | ||||
| 
 | ||||
| app.get("/status", (req, res) => { | ||||
|   // http basic auth handling without 3rd-party lib https://stackoverflow.com/a/33905671
 | ||||
|   const auth = { | ||||
|     login: process.env.MATRIXUSERNAME, | ||||
|     password: process.env.MATRIXPASSWORD | ||||
|   }; | ||||
| 
 | ||||
|   // parse login and password from headers
 | ||||
|   const b64auth = (req.headers.authorization || "").split(" ")[1] || ""; | ||||
|   const [_, login, password] = | ||||
|     new Buffer(b64auth, "base64").toString().match(/(.*):(.*)/) || []; // slightly modified as we use : in username
 | ||||
| 
 | ||||
|   if ( | ||||
|     !login || | ||||
|     !password || | ||||
|     login !== auth.login || | ||||
|     password !== auth.password | ||||
|   ) { | ||||
|     res.set("WWW-Authenticate", 'Basic realm="Authentication required"'); | ||||
|     return res.status(401).send("Authentication required."); | ||||
|   } | ||||
|   fuzIsOpen = req.query.fuzisopen === "1"; | ||||
|   lastSeen = new Date(); | ||||
|   try { | ||||
|     fs.writeFileSync(db, JSON.stringify({ fuzIsOpen, lastSeen, lastOpened, lastClosed })); | ||||
|   } catch (err) {} | ||||
| 
 | ||||
|   res.sendStatus(200); | ||||
|   if ( | ||||
|     fuzIsOpen && | ||||
|     lastOpened < lastClosed | ||||
|   ) { | ||||
|     // the Fuz is newly opened, notify on matrix and write file to survive reboot
 | ||||
|     request.put( | ||||
|       { | ||||
|         url: | ||||
|           "https://" + | ||||
|           process.env.MATRIXUSERNAME.substring( | ||||
|             process.env.MATRIXUSERNAME.indexOf(":") + 1 | ||||
|           ) + | ||||
|           "/_matrix/client/r0/rooms/" + | ||||
|           process.env.MATRIXROOM + | ||||
|           "/send/m.room.message/" + | ||||
|           new Date().getTime() + | ||||
|           "?access_token=" + | ||||
|           accessToken + | ||||
|           "&limit=1", | ||||
|         body: JSON.stringify({ | ||||
|           msgtype: "m.text", | ||||
|           body: | ||||
|             process.env.MATRIXOPENINGMESSAGE | ||||
|         }), | ||||
|         headers: { | ||||
|           "Content-Type": "application/json" | ||||
|         } | ||||
|       }, | ||||
|       function(error, response, body2) { | ||||
|         if (!error) { | ||||
|           try { | ||||
|             lastOpened = new Date(); | ||||
|             fs.writeFileSync( | ||||
|               db, | ||||
|               JSON.stringify({ fuzIsOpen, lastSeen, lastOpened, lastClosed }) | ||||
|             ); | ||||
|           } catch (err) {} | ||||
|         } | ||||
|         console.log(body2); | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
| }); | ||||
| app.all("*", (req, res) => { | ||||
|     res.redirect("https://presence.fuz.re" + req.originalUrl) | ||||
| }) | ||||
| 
 | ||||
| const listener = app.listen(process.env.PORT, function() { | ||||
|   console.log("Your app is listening on port " + listener.address().port); | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| const accessToken = process.env.MATRIXACCESSTOKEN; | ||||
| const loop = () => { | ||||
|   console.log("loop", JSON.stringify({ fuzIsOpen, lastSeen, lastOpened, lastClosed })); | ||||
|   if ( | ||||
|     //fuzIsOpen &&
 | ||||
|     lastSeen < new Date() - defaultClosingTimeout && | ||||
|     lastClosed < lastSeen | ||||
|   ) { | ||||
|     // the Fuz is newly closed, notify on matrix and write file to survive reboot
 | ||||
|     //https.put ... send message to Fuz process.env.MATRIXROOM
 | ||||
|     request.put( | ||||
|       { | ||||
|         url: | ||||
|           "https://" + | ||||
|           process.env.MATRIXUSERNAME.substring( | ||||
|             process.env.MATRIXUSERNAME.indexOf(":") + 1 | ||||
|           ) + | ||||
|           "/_matrix/client/r0/rooms/" + | ||||
|           process.env.MATRIXROOM + | ||||
|           "/send/m.room.message/" + | ||||
|           new Date().getTime() + | ||||
|           "?access_token=" + | ||||
|           accessToken + | ||||
|           "&limit=1", | ||||
|         body: JSON.stringify({ | ||||
|           msgtype: "m.text", | ||||
|           body: | ||||
|             process.env.MATRIXCLOSINGMESSAGE + | ||||
|             (fuzIsOpen ? "" : " (crash, oubli, passage bref…)") | ||||
|         }), | ||||
|         headers: { | ||||
|           "Content-Type": "application/json" | ||||
|         } | ||||
|       }, | ||||
|       function(error, response, body2) { | ||||
|         if (!error) { | ||||
|           try { | ||||
|             lastClosed = new Date(); | ||||
|             fs.writeFileSync( | ||||
|               db, | ||||
|               JSON.stringify({ fuzIsOpen, lastSeen, lastOpened, lastClosed }) | ||||
|             ); | ||||
|           } catch (err) {} | ||||
|         } | ||||
|         console.log(body2); | ||||
|         setTimeout(loop, 10 * 1000); | ||||
|       } | ||||
|     ); | ||||
|   } else { | ||||
|     setTimeout(loop, 10 * 1000); | ||||
|   } | ||||
| }; | ||||
| setTimeout(loop, 1 * 60 * 1000); // give some time for presence button to show up (1 min)
 | ||||
| 
 | ||||
| const formatSeconds = function (seconds) { // https://stackoverflow.com/a/13368349
 | ||||
|   var seconds = Math.floor(seconds), | ||||
|       hours = Math.floor(seconds / 3600); | ||||
|   seconds -= hours*3600; | ||||
|   var minutes = Math.floor(seconds / 60); | ||||
|   seconds -= minutes*60; | ||||
| 
 | ||||
|   if (hours   < 10) {hours   = "0"+hours;} | ||||
|   if (minutes < 10) {minutes = "0"+minutes;} | ||||
|   if (seconds < 10) {seconds = "0"+seconds;} | ||||
|   return hours+':'+minutes+':'+seconds; | ||||
| } | ||||
| 
 | ||||
| if (process.env.PROJECT_DOMAIN != "") { | ||||
|   process.on("SIGTERM", function() { | ||||
|     console.log("SIGTERM received, sending SOS to Resurrect..."); | ||||
|     require("https").get( | ||||
|       "https://resurrect.glitch.me/" + process.env.PROJECT_DOMAIN + "", | ||||
|       process.exit | ||||
|     ); | ||||
|   }); | ||||
| } | ||||
|   console.log("Your app is listening on port " + listener.address().port) | ||||
| }) | ||||
							
								
								
									
										310
									
								
								shrinkwrap.yaml
									
									
									
									
									
								
							
							
						
						
									
										310
									
								
								shrinkwrap.yaml
									
									
									
									
									
								
							| @ -1,6 +1,5 @@ | ||||
| dependencies: | ||||
|   express: 4.17.1 | ||||
|   request: 2.88.2 | ||||
| packages: | ||||
|   /accepts/1.3.7: | ||||
|     dependencies: | ||||
| @ -11,49 +10,10 @@ packages: | ||||
|       node: '>= 0.6' | ||||
|     resolution: | ||||
|       integrity: sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== | ||||
|   /ajv/6.12.2: | ||||
|     dependencies: | ||||
|       fast-deep-equal: 3.1.1 | ||||
|       fast-json-stable-stringify: 2.1.0 | ||||
|       json-schema-traverse: 0.4.1 | ||||
|       uri-js: 4.2.2 | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== | ||||
|   /array-flatten/1.1.1: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= | ||||
|   /asn1/0.2.4: | ||||
|     dependencies: | ||||
|       safer-buffer: 2.1.2 | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== | ||||
|   /assert-plus/1.0.0: | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>=0.8' | ||||
|     resolution: | ||||
|       integrity: sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= | ||||
|   /asynckit/0.4.0: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k= | ||||
|   /aws-sign2/0.7.0: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= | ||||
|   /aws4/1.9.1: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== | ||||
|   /bcrypt-pbkdf/1.0.2: | ||||
|     dependencies: | ||||
|       tweetnacl: 0.14.5 | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= | ||||
|   /body-parser/1.19.0: | ||||
|     dependencies: | ||||
|       bytes: 3.1.0 | ||||
| @ -77,18 +37,6 @@ packages: | ||||
|       node: '>= 0.8' | ||||
|     resolution: | ||||
|       integrity: sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== | ||||
|   /caseless/0.12.0: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= | ||||
|   /combined-stream/1.0.8: | ||||
|     dependencies: | ||||
|       delayed-stream: 1.0.0 | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>= 0.8' | ||||
|     resolution: | ||||
|       integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== | ||||
|   /content-disposition/0.5.3: | ||||
|     dependencies: | ||||
|       safe-buffer: 5.1.2 | ||||
| @ -113,30 +61,12 @@ packages: | ||||
|       node: '>= 0.6' | ||||
|     resolution: | ||||
|       integrity: sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== | ||||
|   /core-util-is/1.0.2: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= | ||||
|   /dashdash/1.14.1: | ||||
|     dependencies: | ||||
|       assert-plus: 1.0.0 | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>=0.10' | ||||
|     resolution: | ||||
|       integrity: sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= | ||||
|   /debug/2.6.9: | ||||
|     dependencies: | ||||
|       ms: 2.0.0 | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== | ||||
|   /delayed-stream/1.0.0: | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>=0.4.0' | ||||
|     resolution: | ||||
|       integrity: sha1-3zrhmayt+31ECqrgsp4icrJOxhk= | ||||
|   /depd/1.1.2: | ||||
|     dev: false | ||||
|     engines: | ||||
| @ -147,13 +77,6 @@ packages: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= | ||||
|   /ecc-jsbn/0.1.2: | ||||
|     dependencies: | ||||
|       jsbn: 0.1.1 | ||||
|       safer-buffer: 2.1.2 | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= | ||||
|   /ee-first/1.1.1: | ||||
|     dev: false | ||||
|     resolution: | ||||
| @ -211,30 +134,6 @@ packages: | ||||
|       node: '>= 0.10.0' | ||||
|     resolution: | ||||
|       integrity: sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== | ||||
|   /extend/3.0.2: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== | ||||
|   /extsprintf/1.3.0: | ||||
|     dev: false | ||||
|     engines: | ||||
|       '0': node >=0.6.0 | ||||
|     resolution: | ||||
|       integrity: sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= | ||||
|   /extsprintf/1.4.0: | ||||
|     dev: false | ||||
|     engines: | ||||
|       '0': node >=0.6.0 | ||||
|     resolution: | ||||
|       integrity: sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= | ||||
|   /fast-deep-equal/3.1.1: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== | ||||
|   /fast-json-stable-stringify/2.1.0: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== | ||||
|   /finalhandler/1.1.2: | ||||
|     dependencies: | ||||
|       debug: 2.6.9 | ||||
| @ -249,20 +148,6 @@ packages: | ||||
|       node: '>= 0.8' | ||||
|     resolution: | ||||
|       integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== | ||||
|   /forever-agent/0.6.1: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= | ||||
|   /form-data/2.3.3: | ||||
|     dependencies: | ||||
|       asynckit: 0.4.0 | ||||
|       combined-stream: 1.0.8 | ||||
|       mime-types: 2.1.27 | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>= 0.12' | ||||
|     resolution: | ||||
|       integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== | ||||
|   /forwarded/0.1.2: | ||||
|     dev: false | ||||
|     engines: | ||||
| @ -275,27 +160,6 @@ packages: | ||||
|       node: '>= 0.6' | ||||
|     resolution: | ||||
|       integrity: sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= | ||||
|   /getpass/0.1.7: | ||||
|     dependencies: | ||||
|       assert-plus: 1.0.0 | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= | ||||
|   /har-schema/2.0.0: | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>=4' | ||||
|     resolution: | ||||
|       integrity: sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= | ||||
|   /har-validator/5.1.3: | ||||
|     dependencies: | ||||
|       ajv: 6.12.2 | ||||
|       har-schema: 2.0.0 | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>=6' | ||||
|     resolution: | ||||
|       integrity: sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== | ||||
|   /http-errors/1.7.2: | ||||
|     dependencies: | ||||
|       depd: 1.1.2 | ||||
| @ -320,17 +184,6 @@ packages: | ||||
|       node: '>= 0.6' | ||||
|     resolution: | ||||
|       integrity: sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== | ||||
|   /http-signature/1.2.0: | ||||
|     dependencies: | ||||
|       assert-plus: 1.0.0 | ||||
|       jsprim: 1.4.1 | ||||
|       sshpk: 1.16.1 | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>=0.8' | ||||
|       npm: '>=1.3.7' | ||||
|     resolution: | ||||
|       integrity: sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= | ||||
|   /iconv-lite/0.4.24: | ||||
|     dependencies: | ||||
|       safer-buffer: 2.1.2 | ||||
| @ -353,41 +206,6 @@ packages: | ||||
|       node: '>= 0.10' | ||||
|     resolution: | ||||
|       integrity: sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== | ||||
|   /is-typedarray/1.0.0: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= | ||||
|   /isstream/0.1.2: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= | ||||
|   /jsbn/0.1.1: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-peZUwuWi3rXyAdls77yoDA7y9RM= | ||||
|   /json-schema-traverse/0.4.1: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== | ||||
|   /json-schema/0.2.3: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= | ||||
|   /json-stringify-safe/5.0.1: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= | ||||
|   /jsprim/1.4.1: | ||||
|     dependencies: | ||||
|       assert-plus: 1.0.0 | ||||
|       extsprintf: 1.3.0 | ||||
|       json-schema: 0.2.3 | ||||
|       verror: 1.10.0 | ||||
|     dev: false | ||||
|     engines: | ||||
|       '0': node >=0.6.0 | ||||
|     resolution: | ||||
|       integrity: sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= | ||||
|   /media-typer/0.3.0: | ||||
|     dev: false | ||||
|     engines: | ||||
| @ -410,12 +228,6 @@ packages: | ||||
|       node: '>= 0.6' | ||||
|     resolution: | ||||
|       integrity: sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== | ||||
|   /mime-db/1.44.0: | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>= 0.6' | ||||
|     resolution: | ||||
|       integrity: sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== | ||||
|   /mime-types/2.1.25: | ||||
|     dependencies: | ||||
|       mime-db: 1.42.0 | ||||
| @ -424,14 +236,6 @@ packages: | ||||
|       node: '>= 0.6' | ||||
|     resolution: | ||||
|       integrity: sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== | ||||
|   /mime-types/2.1.27: | ||||
|     dependencies: | ||||
|       mime-db: 1.44.0 | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>= 0.6' | ||||
|     resolution: | ||||
|       integrity: sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== | ||||
|   /mime/1.6.0: | ||||
|     dev: false | ||||
|     engines: | ||||
| @ -453,10 +257,6 @@ packages: | ||||
|       node: '>= 0.6' | ||||
|     resolution: | ||||
|       integrity: sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== | ||||
|   /oauth-sign/0.9.0: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== | ||||
|   /on-finished/2.3.0: | ||||
|     dependencies: | ||||
|       ee-first: 1.1.1 | ||||
| @ -475,10 +275,6 @@ packages: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= | ||||
|   /performance-now/2.1.0: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= | ||||
|   /proxy-addr/2.0.5: | ||||
|     dependencies: | ||||
|       forwarded: 0.1.2 | ||||
| @ -488,22 +284,6 @@ packages: | ||||
|       node: '>= 0.10' | ||||
|     resolution: | ||||
|       integrity: sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== | ||||
|   /psl/1.8.0: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== | ||||
|   /punycode/2.1.1: | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>=6' | ||||
|     resolution: | ||||
|       integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== | ||||
|   /qs/6.5.2: | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>=0.6' | ||||
|     resolution: | ||||
|       integrity: sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== | ||||
|   /qs/6.7.0: | ||||
|     dev: false | ||||
|     engines: | ||||
| @ -527,42 +307,10 @@ packages: | ||||
|       node: '>= 0.8' | ||||
|     resolution: | ||||
|       integrity: sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== | ||||
|   /request/2.88.2: | ||||
|     dependencies: | ||||
|       aws-sign2: 0.7.0 | ||||
|       aws4: 1.9.1 | ||||
|       caseless: 0.12.0 | ||||
|       combined-stream: 1.0.8 | ||||
|       extend: 3.0.2 | ||||
|       forever-agent: 0.6.1 | ||||
|       form-data: 2.3.3 | ||||
|       har-validator: 5.1.3 | ||||
|       http-signature: 1.2.0 | ||||
|       is-typedarray: 1.0.0 | ||||
|       isstream: 0.1.2 | ||||
|       json-stringify-safe: 5.0.1 | ||||
|       mime-types: 2.1.27 | ||||
|       oauth-sign: 0.9.0 | ||||
|       performance-now: 2.1.0 | ||||
|       qs: 6.5.2 | ||||
|       safe-buffer: 5.2.0 | ||||
|       tough-cookie: 2.5.0 | ||||
|       tunnel-agent: 0.6.0 | ||||
|       uuid: 3.4.0 | ||||
|     deprecated: 'request has been deprecated, see https://github.com/request/request/issues/3142' | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>= 6' | ||||
|     resolution: | ||||
|       integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== | ||||
|   /safe-buffer/5.1.2: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== | ||||
|   /safe-buffer/5.2.0: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== | ||||
|   /safer-buffer/2.1.2: | ||||
|     dev: false | ||||
|     resolution: | ||||
| @ -602,23 +350,6 @@ packages: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== | ||||
|   /sshpk/1.16.1: | ||||
|     dependencies: | ||||
|       asn1: 0.2.4 | ||||
|       assert-plus: 1.0.0 | ||||
|       bcrypt-pbkdf: 1.0.2 | ||||
|       dashdash: 1.14.1 | ||||
|       ecc-jsbn: 0.1.2 | ||||
|       getpass: 0.1.7 | ||||
|       jsbn: 0.1.1 | ||||
|       safer-buffer: 2.1.2 | ||||
|       tweetnacl: 0.14.5 | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>=0.10.0' | ||||
|     hasBin: true | ||||
|     resolution: | ||||
|       integrity: sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== | ||||
|   /statuses/1.5.0: | ||||
|     dev: false | ||||
|     engines: | ||||
| @ -631,25 +362,6 @@ packages: | ||||
|       node: '>=0.6' | ||||
|     resolution: | ||||
|       integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== | ||||
|   /tough-cookie/2.5.0: | ||||
|     dependencies: | ||||
|       psl: 1.8.0 | ||||
|       punycode: 2.1.1 | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>=0.8' | ||||
|     resolution: | ||||
|       integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== | ||||
|   /tunnel-agent/0.6.0: | ||||
|     dependencies: | ||||
|       safe-buffer: 5.2.0 | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= | ||||
|   /tweetnacl/0.14.5: | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= | ||||
|   /type-is/1.6.18: | ||||
|     dependencies: | ||||
|       media-typer: 0.3.0 | ||||
| @ -665,42 +377,20 @@ packages: | ||||
|       node: '>= 0.8' | ||||
|     resolution: | ||||
|       integrity: sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= | ||||
|   /uri-js/4.2.2: | ||||
|     dependencies: | ||||
|       punycode: 2.1.1 | ||||
|     dev: false | ||||
|     resolution: | ||||
|       integrity: sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== | ||||
|   /utils-merge/1.0.1: | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>= 0.4.0' | ||||
|     resolution: | ||||
|       integrity: sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= | ||||
|   /uuid/3.4.0: | ||||
|     dev: false | ||||
|     hasBin: true | ||||
|     resolution: | ||||
|       integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== | ||||
|   /vary/1.1.2: | ||||
|     dev: false | ||||
|     engines: | ||||
|       node: '>= 0.8' | ||||
|     resolution: | ||||
|       integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= | ||||
|   /verror/1.10.0: | ||||
|     dependencies: | ||||
|       assert-plus: 1.0.0 | ||||
|       core-util-is: 1.0.2 | ||||
|       extsprintf: 1.4.0 | ||||
|     dev: false | ||||
|     engines: | ||||
|       '0': node >=0.6.0 | ||||
|     resolution: | ||||
|       integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= | ||||
| registry: 'https://registry.npmjs.org/' | ||||
| shrinkwrapMinorVersion: 9 | ||||
| shrinkwrapVersion: 3 | ||||
| specifiers: | ||||
|   express: ^4.17.1 | ||||
|   request: ^2.88.2 | ||||
|  | ||||
| @ -1 +0,0 @@ | ||||
| <?xml version="1.0" ?><svg viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:#f8991d;}.cls-2{fill:#fd0;}.cls-3{fill:#314967;}</style></defs><title/><g data-name="18 Closed Sign" id="_18_Closed_Sign"><rect class="cls-1" height="36" rx="6" ry="6" width="96" x="16" y="64"/><circle class="cls-2" cx="64" cy="28" r="6"/><path class="cls-3" d="M71.85,77.83a4.37,4.37,0,0,1,2.34,1,1.93,1.93,0,1,0,2.08-3.25A7.94,7.94,0,0,0,71.85,74c-3.13,0-5.55,2.06-5.55,4.58,0,2.74,2.64,4.21,5.35,4.58.55.11,2,.45,2.26,1,0,.57-1.38,1-2,1a5.25,5.25,0,0,1-2.79-1.16,1.93,1.93,0,1,0-2.42,3,8.73,8.73,0,0,0,5.23,2c3.12,0,5.88-2,5.88-4.82s-2.88-4.4-5.66-4.78c-1.6-.31-2-.77-2-.77C70.15,78.39,70.8,77.83,71.85,77.83Z"/><path class="cls-3" d="M40,76.34V87a2,2,0,0,0,2,2h5.83a2,2,0,0,0,0-4H44V76.34A2,2,0,0,0,40,76.34Z"/><path class="cls-3" d="M50,81.48A7.16,7.16,0,1,0,57.23,74,7.32,7.32,0,0,0,50,81.48Zm10.26,0c0,2.89-3.21,4.64-5.27,2.43-1.94-2-.71-5.86,2.2-5.86A3.29,3.29,0,0,1,60.3,81.48Z"/><path class="cls-3" d="M34.44,78.82a2,2,0,0,0,2.49-3.21A7.7,7.7,0,0,0,32.15,74a7.6,7.6,0,0,0-7.6,7.48h0c0,6.3,7.44,9.7,12.39,5.86a2,2,0,0,0-2.51-3.2,3.52,3.52,0,1,1,0-5.31Z"/><path class="cls-3" d="M87.69,78.35a2,2,0,0,0,0-4H81.8a2,2,0,0,0-2,2V87a2,2,0,0,0,1,1.75V89h6.83a2,2,0,0,0,0-4H83.81V83.65H87a2,2,0,0,0,0-4h-3.2V78.35Z"/><path class="cls-3" d="M103.09,81.64a7.29,7.29,0,0,0-7.28-7.28H93.69a2,2,0,0,0-2,2V87a2,2,0,0,0,2,2h2.13A7.31,7.31,0,0,0,103.09,81.64ZM95.81,85h-.12V78.35h.12C100.14,78.35,100.18,84.93,95.81,85Z"/><path class="cls-3" d="M92.73,98H22a4,4,0,0,1-4-4V70a4,4,0,0,1,4-4H42.55a2,2,0,0,0,0-4H32.83L59.93,34.89a8,8,0,0,0,8.13,0L81.71,48.54a2,2,0,0,0,2.83-2.83L70.88,32.06A8,8,0,0,0,64,20a2,2,0,0,0,0,4,4,4,0,0,1,2.79,6.86C63.58,34,58.24,30.08,60.51,26a2,2,0,0,0-3.49-2,8,8,0,0,0,.09,8L27.17,62H22a8,8,0,0,0-8,8V94a8,8,0,0,0,8,8H92.73A2,2,0,0,0,92.73,98Z"/><path class="cls-3" d="M106,62h-5.17L88.09,49.26a2,2,0,0,0-2.83,2.83L95.17,62H76a2,2,0,0,0,0,4h30a4,4,0,0,1,4,4V94a4,4,0,0,1-4,4H98.51a2,2,0,0,0,0,4H106a8,8,0,0,0,8-8V70A8,8,0,0,0,106,62Z"/><path class="cls-3" d="M70,62H49.22a2,2,0,0,0,0,4H70A2,2,0,0,0,70,62Z"/></g></svg> | ||||
| Before Width: | Height: | Size: 2.1 KiB | 
| @ -1,65 +0,0 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
|   <head> | ||||
|     <title>Fuz presence button</title> | ||||
|     <meta | ||||
|       name="description" | ||||
|       content="Public API for Fuz hackerspace presence button" | ||||
|     /> | ||||
|     <link | ||||
|       id="favicon" | ||||
|       rel="icon" | ||||
|       href="https://fuz.frama.site/medias/5c02ae843c25e.jpg" | ||||
|       type="image/x-icon" | ||||
|     /> | ||||
|     <meta charset="utf-8" /> | ||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||
| 
 | ||||
|     <!-- import the webpage's stylesheet --> | ||||
|     <link rel="stylesheet" href="/style.css" /> | ||||
|   </head> | ||||
|   <body> | ||||
|     <header> | ||||
|       <h1> | ||||
|         Fuz presence button public API | ||||
|       </h1> | ||||
|     </header> | ||||
| 
 | ||||
|     <main> | ||||
|       <p> | ||||
|         See documentation for this project on | ||||
|         <a href="https://wiki.fuz.re/doku.php?id=projets:fuz:presence_button" | ||||
|           >Fuz wiki</a | ||||
|         > | ||||
|       </p> | ||||
|       <p>Available endpoints:</p> | ||||
| 
 | ||||
|       <section class="dreams"> | ||||
|         <ul id="dreams"> | ||||
|           <li> | ||||
|             <a href="/img">image API</a | ||||
|             ><img src="/img" height="15px" width="15px" />, you can define a custom closingTimeout parameter to customize the delay after which the space is shown closed (milliseconds, defaults to 5 mins) | ||||
|           </li> | ||||
|           <li><a href="/api">ajax API</a></li> | ||||
|         </ul> | ||||
|       </section> | ||||
|       <h2>API minimalistic documentation</h2> | ||||
|       <p> | ||||
|         <code>{"fuzIsOpen":true,"lastSeen":"2019-11-03T16:25:24.385Z"}</code | ||||
|         ><br /> | ||||
|         The JSON means that the last notification sent by the presence button | ||||
|         was at 2019-11-03T16:25:24.385Z and it was saying that the Fuz was open | ||||
|         at the time. If it's been a while since last notification (lastSeen), we | ||||
|         can conclude the Fuz is now closed. | ||||
|       </p> | ||||
|     </main> | ||||
| 
 | ||||
|     <footer>Made with <a href="https://glitch.com">Glitch</a>!</footer> | ||||
| 
 | ||||
|     <!-- include the Glitch button to show what the webpage is about and | ||||
|           to make it easier for folks to view source and remix --> | ||||
|     <div class="glitchButton" style="position:fixed;top:20px;right:20px;"></div> | ||||
|     <script src="https://button.glitch.me/button.js"></script> | ||||
|   </body> | ||||
| </html> | ||||
| @ -1 +0,0 @@ | ||||
| <?xml version="1.0" ?><svg viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:#5bc9e1;}.cls-2{fill:#fd0;}.cls-3{fill:#314967;}</style></defs><title/><g data-name="15 Open Sign" id="_15_Open_Sign"><rect class="cls-1" height="36" rx="6" ry="6" width="96" x="16" y="64"/><circle class="cls-2" cx="64" cy="28" r="6"/><path class="cls-3" d="M92.73,98H22a4,4,0,0,1-4-4V70a4,4,0,0,1,4-4H42.54a2,2,0,0,0,0-4H32.83L59.93,34.89a8,8,0,0,0,8.13,0L81.71,48.54a2,2,0,0,0,2.83-2.83L70.88,32.06A8,8,0,0,0,64,20a2,2,0,0,0,0,4,4,4,0,1,1-3.49,2,2,2,0,0,0-3.49-2,8,8,0,0,0,.09,8L27.17,62H22a8,8,0,0,0-8,8V94a8,8,0,0,0,8,8H92.73A2,2,0,0,0,92.73,98Z"/><path class="cls-3" d="M106,62h-5.17L88.09,49.26a2,2,0,0,0-2.83,2.83L95.17,62H76a2,2,0,0,0,0,4h30a4,4,0,0,1,4,4V94a4,4,0,0,1-4,4H98.51a2,2,0,0,0,0,4H106a8,8,0,0,0,8-8V70A8,8,0,0,0,106,62Z"/><path class="cls-3" d="M70,62H49.22a2,2,0,0,0,0,4H70A2,2,0,0,0,70,62Z"/><path class="cls-3" d="M54.86,73.62a2.2,2.2,0,0,0-2.19,2.19v12.8a2.2,2.2,0,0,0,4.41,0V84.91h1.67a5.64,5.64,0,1,0,0-11.29ZM60,79.27c0,1.49-1.64,1.23-2.93,1.23V78C58.42,78,60,77.78,60,79.27Z"/><path class="cls-3" d="M77,78c2.86,0,2.93-4.41,0-4.41H69.92a2.17,2.17,0,0,0-2.19,2.19v12.8a2.2,2.2,0,0,0,1.25,2v.21h8c2.91,0,2.87-4.41,0-4.41H72.13v-2h4.06a2.2,2.2,0,0,0,0-4.41H72.13V78Z"/><path class="cls-3" d="M96.63,76c0-2.83-4.37-2.9-4.37,0v5.85l-5.19-7.19A2.18,2.18,0,0,0,83.13,76V88.62a2.18,2.18,0,0,0,4.37,0V82.71l5.1,7.08a2.19,2.19,0,0,0,4-1.17Z"/><path class="cls-3" d="M39.84,73.19a8.82,8.82,0,0,0,0,17.62A8.69,8.69,0,0,0,48.22,82C48.22,77.31,44.49,73.19,39.84,73.19Zm0,13.15c-5.3,0-5.26-8.68,0-8.68a4.36,4.36,0,0,1,0,8.68Z"/></g></svg> | ||||
| Before Width: | Height: | Size: 1.6 KiB | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user