diff --git a/README.md b/README.md new file mode 100644 index 0000000..94d83e0 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# ??? + +# building + +- `task build-backend` +- `task build-frontend` + +# dev +- `task dev-backend` +- `task dev-frontend` +- (in separate terminals) + +# deploy +- `./gw` \ No newline at end of file diff --git a/index.html b/index.html deleted file mode 100644 index f64789e..0000000 --- a/index.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - -
-

???

- Referral: - -

- What is this? -

At exactly 00:00 CET on 1 Jan, the system will choose a random entry. Their referral key shall be publically - displayed on this page. The person associated to this referral key shall contact us with their private key. - They shall win a little prize. To have one's entry weigh more than the rest, one shall have to spread their - referral key amongst the people. Every referral shall increase their chance of getting selected.

- How does one enter? -

One needs a referral key to enter.

-

-

-
- - - - diff --git a/public/assets/index-CHOkfbIW.css b/public/assets/index-CHOkfbIW.css new file mode 100644 index 0000000..a232571 --- /dev/null +++ b/public/assets/index-CHOkfbIW.css @@ -0,0 +1 @@ +*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.mt-3{margin-top:.75rem}.flex{display:flex}.h-full{height:100%}.h-screen{height:100vh}.w-2\/3{width:66.666667%}.w-full{width:100%}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-6{gap:1.5rem}.rounded-lg{border-radius:.5rem}.border-2{border-width:2px}.border-green-500{--tw-border-opacity: 1;border-color:rgb(34 197 94 / var(--tw-border-opacity, 1))}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-800{--tw-bg-opacity: 1;background-color:rgb(22 101 52 / var(--tw-bg-opacity, 1))}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-6xl{font-size:3.75rem;line-height:1}.font-bold{font-weight:700}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity, 1))}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.opacity-100{opacity:1}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.hover\:bg-black:hover{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.hover\:bg-green-500:hover{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.hover\:bg-green-900:hover{--tw-bg-opacity: 1;background-color:rgb(20 83 45 / var(--tw-bg-opacity, 1))}.hover\:text-black:hover{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity, 1))}.hover\:text-green-500:hover{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.hover\:opacity-75:hover{opacity:.75}.active\:bg-green-500:active{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.active\:bg-green-700:active{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity, 1))}.active\:text-black:active{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity, 1))} diff --git a/public/assets/index-Ccw9dgTj.js b/public/assets/index-Ccw9dgTj.js new file mode 100644 index 0000000..8b570d7 --- /dev/null +++ b/public/assets/index-Ccw9dgTj.js @@ -0,0 +1 @@ +(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const _ of document.querySelectorAll('link[rel="modulepreload"]'))n(_);new MutationObserver(_=>{for(const o of _)if(o.type==="childList")for(const c of o.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&n(c)}).observe(document,{childList:!0,subtree:!0});function r(_){const o={};return _.integrity&&(o.integrity=_.integrity),_.referrerPolicy&&(o.referrerPolicy=_.referrerPolicy),_.crossOrigin==="use-credentials"?o.credentials="include":_.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function n(_){if(_.ep)return;_.ep=!0;const o=r(_);fetch(_.href,o)}})();var j,m,De,U,me,Ue,oe,Re,ue,ie,ce,Me,W={},Ae=[],Ze=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,V=Array.isArray;function H(t,e){for(var r in e)t[r]=e[r];return t}function ae(t){t&&t.parentNode&&t.parentNode.removeChild(t)}function R(t,e,r){var n,_,o,c={};for(o in e)o=="key"?n=e[o]:o=="ref"?_=e[o]:c[o]=e[o];if(arguments.length>2&&(c.children=arguments.length>3?j.call(arguments,2):r),typeof t=="function"&&t.defaultProps!=null)for(o in t.defaultProps)c[o]===void 0&&(c[o]=t.defaultProps[o]);return O(t,c,n,_,null)}function O(t,e,r,n,_){var o={type:t,props:e,key:r,ref:n,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:_??++De,__i:-1,__u:0};return _==null&&m.vnode!=null&&m.vnode(o),o}function ee(t){return t.children}function Z(t,e){this.props=t,this.context=e}function F(t,e){if(e==null)return t.__?F(t.__,t.__i+1):null;for(var r;ee&&U.sort(oe));Q.__r=0}function Ie(t,e,r,n,_,o,c,l,u,s,h){var i,a,f,g,w,y,p=n&&n.__k||Ae,v=e.length;for(u=Ye(r,e,p,u,v),i=0;i0?O(c.type,c.props,c.key,c.ref?c.ref:null,c.__v):c).__=t,c.__b=t.__b+1,l=null,(s=c.__i=Qe(c,r,u,i))!==-1&&(i--,(l=r[s])&&(l.__u|=2)),l==null||l.__v===null?(s==-1&&a--,typeof c.type!="function"&&(c.__u|=4)):s!=u&&(s==u-1?a--:s==u+1?a++:(s>u?a--:a++,c.__u|=4))):t.__k[o]=null;if(i)for(o=0;o(u!=null&&!(2&u.__u)?1:0))for(_=r-1,o=r+1;_>=0||o=0){if((u=e[_])&&!(2&u.__u)&&c==u.key&&l===u.type)return _;_--}if(o2&&(l.children=arguments.length>3?j.call(arguments,2):r),O(t.type,l,n||t.key,_||t.ref,null)}function qe(t,e){var r={__c:e="__cC"+Me++,__:t,Consumer:function(n,_){return n.children(_)},Provider:function(n){var _,o;return this.getChildContext||(_=new Set,(o={})[e]=this,this.getChildContext=function(){return o},this.componentWillUnmount=function(){_=null},this.shouldComponentUpdate=function(c){this.props.value!==c.value&&_.forEach(function(l){l.__e=!0,le(l)})},this.sub=function(c){_.add(c);var l=c.componentWillUnmount;c.componentWillUnmount=function(){_&&_.delete(c),l&&l.call(c)}}),n.children}};return r.Provider.__=r.Consumer.contextType=r}j=Ae.slice,m={__e:function(t,e,r,n){for(var _,o,c;e=e.__;)if((_=e.__c)&&!_.__)try{if((o=_.constructor)&&o.getDerivedStateFromError!=null&&(_.setState(o.getDerivedStateFromError(t)),c=_.__d),_.componentDidCatch!=null&&(_.componentDidCatch(t,n||{}),c=_.__d),c)return _.__E=_}catch(l){t=l}throw t}},De=0,Z.prototype.setState=function(t,e){var r;r=this.__s!=null&&this.__s!==this.state?this.__s:this.__s=H({},this.state),typeof t=="function"&&(t=t(H({},r),this.props)),t&&H(r,t),t!=null&&this.__v&&(e&&this._sb.push(e),le(this))},Z.prototype.forceUpdate=function(t){this.__v&&(this.__e=!0,t&&this.__h.push(t),le(this))},Z.prototype.render=ee,U=[],Ue=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,oe=function(t,e){return t.__v.__b-e.__v.__b},Q.__r=0,Re=/(PointerCapture)$|Capture$/i,ue=0,ie=ye(!1),ce=ye(!0),Me=0;var tt=0;function d(t,e,r,n,_,o){e||(e={});var c,l,u=e;if("ref"in u)for(l in u={},e)l=="ref"?c=e[l]:u[l]=e[l];var s={type:t,props:u,key:r,ref:c,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--tt,__i:-1,__u:0,__source:_,__self:o};if(typeof t=="function"&&(c=t.defaultProps))for(l in c)u[l]===void 0&&(u[l]=c[l]);return m.vnode&&m.vnode(s),s}var M,b,te,ke,X=0,Ke=[],k=m,xe=k.__b,we=k.__r,Ee=k.diffed,Ce=k.__c,Pe=k.unmount,Te=k.__;function q(t,e){k.__h&&k.__h(b,t,X||e),X=0;var r=b.__H||(b.__H={__:[],__h:[]});return t>=r.__.length&&r.__.push({}),r.__[t]}function re(t){return X=1,pe(Ge,t)}function pe(t,e,r){var n=q(M++,2);if(n.t=t,!n.__c&&(n.__=[Ge(void 0,e),function(l){var u=n.__N?n.__N[0]:n.__[0],s=n.t(u,l);u!==s&&(n.__N=[s,n.__[1]],n.__c.setState({}))}],n.__c=b,!b.u)){var _=function(l,u,s){if(!n.__c.__H)return!0;var h=n.__c.__H.__.filter(function(a){return!!a.__c});if(h.every(function(a){return!a.__N}))return!o||o.call(this,l,u,s);var i=n.__c.props!==l;return h.forEach(function(a){if(a.__N){var f=a.__[0];a.__=a.__N,a.__N=void 0,f!==a.__[0]&&(i=!0)}}),o&&o.call(this,l,u,s)||i};b.u=!0;var o=b.shouldComponentUpdate,c=b.componentWillUpdate;b.componentWillUpdate=function(l,u,s){if(this.__e){var h=o;o=void 0,_(l,u,s),o=h}c&&c.call(this,l,u,s)},b.shouldComponentUpdate=_}return n.__N||n.__}function $e(t,e){var r=q(M++,3);!k.__s&&ve(r.__H,e)&&(r.__=t,r.i=e,b.__H.__h.push(r))}function ze(t,e){var r=q(M++,4);!k.__s&&ve(r.__H,e)&&(r.__=t,r.i=e,b.__h.push(r))}function $(t){return X=5,de(function(){return{current:t}},[])}function de(t,e){var r=q(M++,7);return ve(r.__H,e)&&(r.__=t(),r.__H=e,r.__h=t),r.__}function Be(t){var e=b.context[t.__c],r=q(M++,9);return r.c=t,e?(r.__==null&&(r.__=!0,e.sub(b)),e.props.value):t.__}function rt(){for(var t;t=Ke.shift();)if(t.__P&&t.__H)try{t.__H.__h.forEach(Y),t.__H.__h.forEach(se),t.__H.__h=[]}catch(e){t.__H.__h=[],k.__e(e,t.__v)}}k.__b=function(t){b=null,xe&&xe(t)},k.__=function(t,e){t&&e.__k&&e.__k.__m&&(t.__m=e.__k.__m),Te&&Te(t,e)},k.__r=function(t){we&&we(t),M=0;var e=(b=t.__c).__H;e&&(te===b?(e.__h=[],b.__h=[],e.__.forEach(function(r){r.__N&&(r.__=r.__N),r.i=r.__N=void 0})):(e.__h.forEach(Y),e.__h.forEach(se),e.__h=[],M=0)),te=b},k.diffed=function(t){Ee&&Ee(t);var e=t.__c;e&&e.__H&&(e.__H.__h.length&&(Ke.push(e)!==1&&ke===k.requestAnimationFrame||((ke=k.requestAnimationFrame)||nt)(rt)),e.__H.__.forEach(function(r){r.i&&(r.__H=r.i),r.i=void 0})),te=b=null},k.__c=function(t,e){e.some(function(r){try{r.__h.forEach(Y),r.__h=r.__h.filter(function(n){return!n.__||se(n)})}catch(n){e.some(function(_){_.__h&&(_.__h=[])}),e=[],k.__e(n,r.__v)}}),Ce&&Ce(t,e)},k.unmount=function(t){Pe&&Pe(t);var e,r=t.__c;r&&r.__H&&(r.__H.__.forEach(function(n){try{Y(n)}catch(_){e=_}}),r.__H=void 0,e&&k.__e(e,r.__v))};var He=typeof requestAnimationFrame=="function";function nt(t){var e,r=function(){clearTimeout(n),He&&cancelAnimationFrame(e),setTimeout(t)},n=setTimeout(r,100);He&&(e=requestAnimationFrame(r))}function Y(t){var e=b,r=t.__c;typeof r=="function"&&(t.__c=void 0,r()),b=e}function se(t){var e=b;t.__c=t.__(),b=e}function ve(t,e){return!t||t.length!==e.length||e.some(function(r,n){return r!==t[n]})}function Ge(t,e){return typeof e=="function"?e(t):e}let D,N;const _t=(t,e)=>{if(D=void 0,e&&e.type==="click"){if(e.ctrlKey||e.metaKey||e.altKey||e.shiftKey||e.button!==0)return t;const r=e.target.closest("a[href]"),n=r&&r.getAttribute("href");if(!r||r.origin!=location.origin||/^#/.test(n)||!/^(_?self)?$/i.test(r.target)||N&&(typeof N=="string"?!n.startsWith(N):!N.test(n)))return t;D=!0,e.preventDefault(),e=r.href.replace(location.origin,"")}else typeof e=="string"?D=!0:e&&e.url?(D=!e.replace,e=e.url):e=location.pathname+location.search;return D===!0?history.pushState(null,"",e):D===!1&&history.replaceState(null,"",e),e},ot=(t,e,r)=>{t=t.split("/").filter(Boolean),e=(e||"").split("/").filter(Boolean);for(let n=0,_,o;n{const o=new URL(e,location.origin),c=o.pathname.replace(/\/+$/g,"")||"/";return{url:e,path:c,query:Object.fromEntries(o.searchParams),route:(l,u)=>r({url:l,replace:u}),wasPush:n}},[e]);return ze(()=>(addEventListener("click",r),addEventListener("popstate",r),()=>{removeEventListener("click",r),removeEventListener("popstate",r)}),[]),R(K.ctx.Provider,{value:_},t.children)}const it=Promise.resolve();function Je(t){const[e,r]=pe(x=>x+1,0),{url:n,query:_,wasPush:o,path:c}=ct(),{rest:l=c,params:u={}}=Be(Se),s=$(!1),h=$(c),i=$(0),a=$(),f=$(),g=$(),w=$(!1),y=$();y.current=!1;const p=$(!1);let v,S,E;Oe(t.children).some(x=>{if(ot(l,x.props.path,E={...x.props,path:l,query:_,params:u,rest:""}))return v=be(x,E);x.props.default&&(S=be(x,E))});let P=v||S;de(()=>{f.current=a.current;const x=f.current&&f.current.props.children;!x||!P||P.type!==x.type||P.props.component!==x.props.component?(this.__v&&this.__v.__k&&this.__v.__k.reverse(),i.current++,p.current=!0):p.current=!1},[n]);const L=a.current&&a.current.__u&G&&a.current.__u&J,z=a.current&&a.current.__h;a.current=R(Se.Provider,{value:E},P),L?(a.current.__u|=G,a.current.__u|=J):z&&(a.current.__h=!0);const A=f.current;return f.current=null,this.__c=(x,T)=>{y.current=!0,f.current=A,t.onLoadStart&&t.onLoadStart(n),s.current=!0;let C=i.current;x.then(()=>{C===i.current&&(f.current=null,a.current&&(T.__h&&(a.current.__h=T.__h),T.__u&J&&(a.current.__u|=J),T.__u&G&&(a.current.__u|=G)),it.then(r))})},ze(()=>{const x=this.__v&&this.__v.__e;if(y.current){!w.current&&!g.current&&(g.current=x);return}!w.current&&g.current&&(g.current!==x&&g.current.remove(),g.current=null),w.current=!0,h.current!==c&&(o&&scrollTo(0,0),t.onRouteChange&&t.onRouteChange(n),h.current=c),t.onLoadEnd&&s.current&&t.onLoadEnd(n),s.current=!1},[c,o,e]),p.current?[R(ne,{r:a}),R(ne,{r:f})]:R(ne,{r:a})}const G=32,J=128,ne=({r:t})=>t.current;Je.Provider=K;K.ctx=qe({});const Se=qe({}),_e=t=>R(t.component,t),ct=()=>Be(K.ctx),Le=m.__e;m.__e=(t,e,r)=>{if(t&&t.then){let n=e;for(;n=n.__;)if(n.__c&&n.__c.__c)return e.__e==null&&(e.__e=r.__e,e.__k=r.__k),e.__k||(e.__k=[]),n.__c.__c(t,e)}Le&&Le(t,e,r)};function lt(){return d("section",{children:[d("h1",{children:"404: Not Found"}),d("p",{children:"It's gone :("})]})}const st=()=>d("div",{class:"flex w-full h-full justify-center items-center",children:d("h1",{class:"font-bold text-red-500 text-2xl",children:"nice try."})}),ut=()=>{const[t,e]=re(""),[r,n]=re({err:!0,referral:"",key:""}),[_,o]=re("...");$e(()=>{console.log("Referral:",t)},[t]);const c=async()=>{let h=await fetch("http://localhost:8080/entry",{method:"GET",headers:{referral:t}});if(!h.ok){console.error("Error:",h.status);return}let i=await h.json();if(i.err){console.error("Error:",i.referral),window.location.href="/error";return}console.log("Entry:",i),n(i),e("")},l=new Date("2025-01-01T00:00:00Z"),u=new Intl.DateTimeFormat(void 0,{year:"numeric",month:"long",day:"numeric",hour:"2-digit",minute:"2-digit",timeZoneName:"short"}).format(l),s=h=>{const i=new Date,a=h.getTime()-i.getTime(),f=Math.floor(a/(1e3*60*60*24)),g=Math.floor(a/(1e3*60*60)%24),w=Math.floor(a/(1e3*60)%60),y=Math.floor(a/1e3%60);let p="";return f>0&&(p+=f+"d "),g>0&&(p+=g+"h "),w>0&&(p+=w+"m "),y>0&&(p+=y+"s"),p===""?p="the time is upon us.":p+=" remaining.",p};return $e(()=>{const h=setInterval(()=>{o(s(l))},1e3);return()=>clearInterval(h)},[]),d("div",{class:"flex flex-col gap-6 w-full h-full justify-center items-center",children:[d("h1",{class:"text-6xl font-bold animate-pulse",children:"???"}),d("p",{children:_}),d("span",{children:[d("p",{class:"opacity-100 hover:opacity-75 transition-opacity",children:"Referral:"}),d("div",{class:"flex gap-2",children:[d("input",{type:"text",value:t,onInput:h=>e(h.currentTarget.value),class:"bg-black text-green-500 border-green-500 border-2 px-2 hover:bg-green-500 hover:text-black active:bg-green-500 active:text-black transition-colors"}),d("button",{onClick:async()=>await c(),class:"bg-green-500 text-black hover:bg-black hover:text-green-500 transition-colors px-4",children:"Submit"})]})]}),r.err?d("div",{class:"w-2/3 text-center flex flex-col gap-2",children:[d("div",{children:[d("b",{children:"What is this?"}),d("p",{children:["At exactly ",u," (00:00 CET on 1 Jan), the system will choose a random entry. Their referral key shall be publicly displayed on this page. The person associated with this referral key shall contact us with their private key. They shall win a little prize. To have one's entry weigh more than the rest, one shall have to spread their referral key amongst people. Every referral shall increase their chance of getting selected."]})]}),d("div",{children:[d("b",{children:"How does one enter?"}),d("p",{children:"One needs a referral key to enter."})]})]}):d("div",{class:"flex flex-col gap-1.5 mt-3 justify-center items-center",children:[d("p",{class:"text-green-700",children:"tip: click to copy."}),d("h2",{onClick:()=>navigator.clipboard.writeText(r==null?void 0:r.key),children:["Key: ",d("code",{class:"cursor-pointer bg-green-800 hover:bg-green-900 active:bg-green-700 transition-colors py-1 px-2 rounded-lg text-white",children:r==null?void 0:r.key})]}),d("h2",{onClick:()=>navigator.clipboard.writeText(r==null?void 0:r.referral),children:["Referral: ",d("code",{class:"cursor-pointer bg-green-800 hover:bg-green-900 active:bg-green-700 transition-colors py-1 px-2 rounded-lg text-white",children:r==null?void 0:r.referral})]}),d("p",{class:"text-green-700",children:"good luck. keep note of these, if you lose them, you can't reroll."})]})]})};function at(){return d(K,{children:d("div",{class:"bg-black text-green-500 h-screen p-4",children:d(Je,{children:[d(_e,{path:"/",component:ut}),d(_e,{default:!0,component:lt}),d(_e,{path:"/error",component:st})]})})})}et(d(at,{}),document.getElementById("app")); diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..91bce6c --- /dev/null +++ b/public/index.html @@ -0,0 +1,15 @@ + + + + + + + + Vite + Preact + + + + +
+ + diff --git a/public/standard.js b/public/standard.js deleted file mode 100644 index 7303728..0000000 --- a/public/standard.js +++ /dev/null @@ -1,16 +0,0 @@ -async function entry() { - var request = await fetch("/entry", { - headers: { - referral: document.getElementById("referral-other").value - } - }) - var body = await request.json(); - - document.getElementById("referral-key").innerText = body.referral; - document.getElementById("private-key").innerText = body.key; - - if(body.err) { - document.getElementById("lelelelele").innerHTML = `

Do not mess with me.

` - } -} - diff --git a/public/vite.svg b/public/vite.svg new file mode 100644 index 0000000..ffcb6bc --- /dev/null +++ b/public/vite.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/sqlite3_64.def b/sqlite3_64.def new file mode 100644 index 0000000..31c9e3c --- /dev/null +++ b/sqlite3_64.def @@ -0,0 +1,362 @@ +EXPORTS +sqlite3_aggregate_context +sqlite3_aggregate_count +sqlite3_auto_extension +sqlite3_autovacuum_pages +sqlite3_backup_finish +sqlite3_backup_init +sqlite3_backup_pagecount +sqlite3_backup_remaining +sqlite3_backup_step +sqlite3_bind_blob +sqlite3_bind_blob64 +sqlite3_bind_double +sqlite3_bind_int +sqlite3_bind_int64 +sqlite3_bind_null +sqlite3_bind_parameter_count +sqlite3_bind_parameter_index +sqlite3_bind_parameter_name +sqlite3_bind_pointer +sqlite3_bind_text +sqlite3_bind_text16 +sqlite3_bind_text64 +sqlite3_bind_value +sqlite3_bind_zeroblob +sqlite3_bind_zeroblob64 +sqlite3_blob_bytes +sqlite3_blob_close +sqlite3_blob_open +sqlite3_blob_read +sqlite3_blob_reopen +sqlite3_blob_write +sqlite3_busy_handler +sqlite3_busy_timeout +sqlite3_cancel_auto_extension +sqlite3_changes +sqlite3_changes64 +sqlite3_clear_bindings +sqlite3_close +sqlite3_close_v2 +sqlite3_collation_needed +sqlite3_collation_needed16 +sqlite3_column_blob +sqlite3_column_bytes +sqlite3_column_bytes16 +sqlite3_column_count +sqlite3_column_database_name +sqlite3_column_database_name16 +sqlite3_column_decltype +sqlite3_column_decltype16 +sqlite3_column_double +sqlite3_column_int +sqlite3_column_int64 +sqlite3_column_name +sqlite3_column_name16 +sqlite3_column_origin_name +sqlite3_column_origin_name16 +sqlite3_column_table_name +sqlite3_column_table_name16 +sqlite3_column_text +sqlite3_column_text16 +sqlite3_column_type +sqlite3_column_value +sqlite3_commit_hook +sqlite3_compileoption_get +sqlite3_compileoption_used +sqlite3_complete +sqlite3_complete16 +sqlite3_config +sqlite3_context_db_handle +sqlite3_create_collation +sqlite3_create_collation_v2 +sqlite3_create_collation16 +sqlite3_create_filename +sqlite3_create_function +sqlite3_create_function_v2 +sqlite3_create_function16 +sqlite3_create_module +sqlite3_create_module_v2 +sqlite3_create_window_function +sqlite3_data_count +sqlite3_data_directory +sqlite3_database_file_object +sqlite3_db_cacheflush +sqlite3_db_config +sqlite3_db_filename +sqlite3_db_handle +sqlite3_db_mutex +sqlite3_db_name +sqlite3_db_readonly +sqlite3_db_release_memory +sqlite3_db_status +sqlite3_declare_vtab +sqlite3_deserialize +sqlite3_drop_modules +sqlite3_enable_load_extension +sqlite3_enable_shared_cache +sqlite3_errcode +sqlite3_errmsg +sqlite3_errmsg16 +sqlite3_error_offset +sqlite3_errstr +sqlite3_exec +sqlite3_expanded_sql +sqlite3_expired +sqlite3_extended_errcode +sqlite3_extended_result_codes +sqlite3_file_control +sqlite3_filename_database +sqlite3_filename_journal +sqlite3_filename_wal +sqlite3_finalize +sqlite3_free +sqlite3_free_filename +sqlite3_free_table +sqlite3_get_autocommit +sqlite3_get_auxdata +sqlite3_get_clientdata +sqlite3_get_table +sqlite3_global_recover +sqlite3_hard_heap_limit64 +sqlite3_initialize +sqlite3_interrupt +sqlite3_is_interrupted +sqlite3_keyword_check +sqlite3_keyword_count +sqlite3_keyword_name +sqlite3_last_insert_rowid +sqlite3_libversion +sqlite3_libversion_number +sqlite3_limit +sqlite3_load_extension +sqlite3_log +sqlite3_malloc +sqlite3_malloc64 +sqlite3_memory_alarm +sqlite3_memory_highwater +sqlite3_memory_used +sqlite3_mprintf +sqlite3_msize +sqlite3_mutex_alloc +sqlite3_mutex_enter +sqlite3_mutex_free +sqlite3_mutex_leave +sqlite3_mutex_try +sqlite3_next_stmt +sqlite3_open +sqlite3_open_v2 +sqlite3_open16 +sqlite3_os_end +sqlite3_os_init +sqlite3_overload_function +sqlite3_prepare +sqlite3_prepare_v2 +sqlite3_prepare_v3 +sqlite3_prepare16 +sqlite3_prepare16_v2 +sqlite3_prepare16_v3 +sqlite3_preupdate_blobwrite +sqlite3_preupdate_count +sqlite3_preupdate_depth +sqlite3_preupdate_hook +sqlite3_preupdate_new +sqlite3_preupdate_old +sqlite3_profile +sqlite3_progress_handler +sqlite3_randomness +sqlite3_realloc +sqlite3_realloc64 +sqlite3_release_memory +sqlite3_reset +sqlite3_reset_auto_extension +sqlite3_result_blob +sqlite3_result_blob64 +sqlite3_result_double +sqlite3_result_error +sqlite3_result_error_code +sqlite3_result_error_nomem +sqlite3_result_error_toobig +sqlite3_result_error16 +sqlite3_result_int +sqlite3_result_int64 +sqlite3_result_null +sqlite3_result_pointer +sqlite3_result_subtype +sqlite3_result_text +sqlite3_result_text16 +sqlite3_result_text16be +sqlite3_result_text16le +sqlite3_result_text64 +sqlite3_result_value +sqlite3_result_zeroblob +sqlite3_result_zeroblob64 +sqlite3_rollback_hook +sqlite3_rtree_geometry_callback +sqlite3_rtree_query_callback +sqlite3_serialize +sqlite3_set_authorizer +sqlite3_set_auxdata +sqlite3_set_clientdata +sqlite3_set_last_insert_rowid +sqlite3_shutdown +sqlite3_sleep +sqlite3_snprintf +sqlite3_soft_heap_limit +sqlite3_soft_heap_limit64 +sqlite3_sourceid +sqlite3_sql +sqlite3_status +sqlite3_status64 +sqlite3_step +sqlite3_stmt_busy +sqlite3_stmt_explain +sqlite3_stmt_isexplain +sqlite3_stmt_readonly +sqlite3_stmt_status +sqlite3_str_append +sqlite3_str_appendall +sqlite3_str_appendchar +sqlite3_str_appendf +sqlite3_str_errcode +sqlite3_str_finish +sqlite3_str_length +sqlite3_str_new +sqlite3_str_reset +sqlite3_str_value +sqlite3_str_vappendf +sqlite3_strglob +sqlite3_stricmp +sqlite3_strlike +sqlite3_strnicmp +sqlite3_system_errno +sqlite3_table_column_metadata +sqlite3_temp_directory +sqlite3_test_control +sqlite3_thread_cleanup +sqlite3_threadsafe +sqlite3_total_changes +sqlite3_total_changes64 +sqlite3_trace +sqlite3_trace_v2 +sqlite3_transfer_bindings +sqlite3_txn_state +sqlite3_update_hook +sqlite3_uri_boolean +sqlite3_uri_int64 +sqlite3_uri_key +sqlite3_uri_parameter +sqlite3_user_data +sqlite3_value_blob +sqlite3_value_bytes +sqlite3_value_bytes16 +sqlite3_value_double +sqlite3_value_dup +sqlite3_value_encoding +sqlite3_value_free +sqlite3_value_frombind +sqlite3_value_int +sqlite3_value_int64 +sqlite3_value_nochange +sqlite3_value_numeric_type +sqlite3_value_pointer +sqlite3_value_subtype +sqlite3_value_text +sqlite3_value_text16 +sqlite3_value_text16be +sqlite3_value_text16le +sqlite3_value_type +sqlite3_version +sqlite3_vfs_find +sqlite3_vfs_register +sqlite3_vfs_unregister +sqlite3_vmprintf +sqlite3_vsnprintf +sqlite3_vtab_collation +sqlite3_vtab_config +sqlite3_vtab_distinct +sqlite3_vtab_in +sqlite3_vtab_in_first +sqlite3_vtab_in_next +sqlite3_vtab_nochange +sqlite3_vtab_on_conflict +sqlite3_vtab_rhs_value +sqlite3_wal_autocheckpoint +sqlite3_wal_checkpoint +sqlite3_wal_checkpoint_v2 +sqlite3_wal_hook +sqlite3_win32_is_nt +sqlite3_win32_mbcs_to_utf8 +sqlite3_win32_mbcs_to_utf8_v2 +sqlite3_win32_set_directory +sqlite3_win32_set_directory16 +sqlite3_win32_set_directory8 +sqlite3_win32_sleep +sqlite3_win32_unicode_to_utf8 +sqlite3_win32_utf8_to_mbcs +sqlite3_win32_utf8_to_mbcs_v2 +sqlite3_win32_utf8_to_unicode +sqlite3_win32_write_debug +sqlite3changegroup_add +sqlite3changegroup_add_change +sqlite3changegroup_add_strm +sqlite3changegroup_delete +sqlite3changegroup_new +sqlite3changegroup_output +sqlite3changegroup_output_strm +sqlite3changegroup_schema +sqlite3changeset_apply +sqlite3changeset_apply_strm +sqlite3changeset_apply_v2 +sqlite3changeset_apply_v2_strm +sqlite3changeset_concat +sqlite3changeset_concat_strm +sqlite3changeset_conflict +sqlite3changeset_finalize +sqlite3changeset_fk_conflicts +sqlite3changeset_invert +sqlite3changeset_invert_strm +sqlite3changeset_new +sqlite3changeset_next +sqlite3changeset_old +sqlite3changeset_op +sqlite3changeset_pk +sqlite3changeset_start +sqlite3changeset_start_strm +sqlite3changeset_start_v2 +sqlite3changeset_start_v2_strm +sqlite3rbu_bp_progress +sqlite3rbu_close +sqlite3rbu_create_vfs +sqlite3rbu_db +sqlite3rbu_destroy_vfs +sqlite3rbu_open +sqlite3rbu_progress +sqlite3rbu_rename_handler +sqlite3rbu_savestate +sqlite3rbu_state +sqlite3rbu_step +sqlite3rbu_temp_size +sqlite3rbu_temp_size_limit +sqlite3rbu_vacuum +sqlite3rebaser_configure +sqlite3rebaser_create +sqlite3rebaser_delete +sqlite3rebaser_rebase +sqlite3rebaser_rebase_strm +sqlite3session_attach +sqlite3session_changeset +sqlite3session_changeset_size +sqlite3session_changeset_strm +sqlite3session_config +sqlite3session_create +sqlite3session_delete +sqlite3session_diff +sqlite3session_enable +sqlite3session_indirect +sqlite3session_isempty +sqlite3session_memory_used +sqlite3session_object_config +sqlite3session_patchset +sqlite3session_patchset_strm +sqlite3session_table_filter diff --git a/sqlite3_64.dll b/sqlite3_64.dll new file mode 100644 index 0000000..ad8714f Binary files /dev/null and b/sqlite3_64.dll differ diff --git a/src/gw.nim b/src/gw.nim index 9d67f3d..7af20e9 100644 --- a/src/gw.nim +++ b/src/gw.nim @@ -16,7 +16,7 @@ sql"""CREATE TABLE IF NOT EXISTS keys( proc index*(ctx: Context) {.async.} = for x in db.fastRows(sql"SELECT * FROM keys"): echo x - await ctx.staticFileResponse("web/index.html", "") + await ctx.staticFileResponse("public/index.html", "") proc ip_exists*(ip: string): bool = return len(db.getAllRows(sql"SELECT * FROM keys WHERE ip=?", ip)) != 0 diff --git a/taskfile.yml b/taskfile.yml index 1b4306c..5fc1527 100644 --- a/taskfile.yml +++ b/taskfile.yml @@ -1,13 +1,13 @@ version: '3' tasks: - build: + build-backend: cmds: - # build backend - rm gw - nimble c -d:usestd src/gw.nim -o:gw - # build frontend - - cd web + build-frontend: + dir: ./web + cmds: - pnpm install - pnpm run build dev-backend: diff --git a/web/src/pages/Home/index.tsx b/web/src/pages/Home/index.tsx index daeea77..4fa7fea 100644 --- a/web/src/pages/Home/index.tsx +++ b/web/src/pages/Home/index.tsx @@ -1,107 +1,144 @@ import { useEffect, useState } from 'preact/hooks'; type EntryBody = { - err: boolean; - referral: string; - key: string; + err: boolean; + referral: string; + key: string; } - export const Home = () => { - const [referral, setReferral] = useState(''); - const [entryBody, setEntryBody] = useState({ - err: true, - referral: '', - key: '' - }); + const [referral, setReferral] = useState(''); + const [entryBody, setEntryBody] = useState({ + err: true, + referral: '', + key: '' + }); + + const [timeLeft, setTimeLeft] = useState('...'); + + useEffect(() => { + console.log('Referral:', referral); + }, [referral]); + + const entry = async () => { + let res = await fetch("http://localhost:8080/entry", { + method: 'GET', + headers: { referral } + }) + + if (!res.ok) { + console.error('Error:', res.status); + return + } + + let body: EntryBody = await res.json(); + + if (body.err) { + console.error('Error:', body.referral); + window.location.href = '/error'; + + return + } + + console.log('Entry:', body); + + setEntryBody(body); + + setReferral(''); + } + + const eventDateCET = new Date('2025-01-01T00:00:00Z'); + const userTime = new Intl.DateTimeFormat(undefined, { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: '2-digit', + minute: '2-digit', + timeZoneName: 'short' + }).format(eventDateCET); + + const getTimeLeft = (date: Date) => { + const now = new Date(); + const diff = date.getTime() - now.getTime(); + const days = Math.floor(diff / (1000 * 60 * 60 * 24)); + const hours = Math.floor(diff / (1000 * 60 * 60) % 24); + const minutes = Math.floor(diff / (1000 * 60) % 60); + const seconds = Math.floor(diff / 1000 % 60); + + let s = ""; + if (days > 0) s += days + "d "; + if (hours > 0) s += hours + "h "; + if (minutes > 0) s += minutes + "m "; + if (seconds > 0) s += seconds + "s"; + + if (s === "") s = "the time is upon us."; + else s += " remaining."; + return s; + } useEffect(() => { - console.log('Referral:', referral); - }, [referral]); + const interval = setInterval(() => { + setTimeLeft(getTimeLeft(eventDateCET)); + }, 1000); - const entry = async () => { - let res = await fetch("http://localhost:8080/entry", { - method: 'GET', - headers: { referral } - }) - - if (!res.ok) { - console.error('Error:', res.status); - return - } + return () => clearInterval(interval); + }, []); - let body: EntryBody = await res.json(); + return ( +
+

???

+

{timeLeft}

+ + +

+ Referral: +

+ + +
+ setReferral(e.currentTarget.value)} - if (body.err) { - console.error('Error:', body.referral); - window.location.href = '/error'; + class="bg-black text-green-500 border-green-500 border-2 px-2 hover:bg-green-500 hover:text-black active:bg-green-500 active:text-black transition-colors" + /> - return - } + +
+
- console.log('Entry:', body); - - setEntryBody(body); + { + !entryBody.err ? ( +
+

tip: click to copy.

+

navigator.clipboard.writeText(entryBody?.key)}>Key: {entryBody?.key}

+

navigator.clipboard.writeText(entryBody?.referral)}>Referral: {entryBody?.referral}

+

good luck. keep note of these, if you lose them, you can't reroll.

+
+ ) : ( +
+
+ What is this? +

At exactly {userTime} (00:00 CET on 1 Jan), the system will choose a random entry. Their referral key shall be publicly + displayed on this page. The person associated with this referral key shall contact us with their private key. + They shall win a little prize. To have one's entry weigh more than the rest, one shall have to spread their + referral key amongst people. Every referral shall increase their chance of getting selected. +

+
- setReferral(''); - } - - return ( -
-

???

-

time left here

-
- -

- Referral: -

- - -
- setReferral(e.currentTarget.value)} - - class="bg-black text-green-500 border-green-500 border-2 px-2 hover:bg-green-500 hover:text-black active:bg-green-500 active:text-black transition-colors" - /> - - -
-
- - { - !entryBody.err ? ( -
-

tip: click to copy.

-

navigator.clipboard.writeText(entryBody?.key)}>Key: {entryBody?.key}

-

navigator.clipboard.writeText(entryBody?.referral)}>Referral: {entryBody?.referral}

-

good luck. keep note of these, if you lose them, you can't reroll.

-
- ) : ( -
-
- What is this? -

At exactly 00:00 CET on 1 Jan, the system will choose a random entry. Their referral key shall be publically - displayed on this page. The person associated to this referral key shall contact us with their private key. - They shall win a little prize. To have one's entry weigh more than the rest, one shall have to spread their - referral key amongst the people. Every referral shall increase their chance of getting selected. -

-
- -
- How does one enter? -

One needs a referral key to enter.

-
-
- ) - } -
+
+ How does one enter? +

One needs a referral key to enter.

+
+
+ ) + }
- ) + ) }; \ No newline at end of file diff --git a/web/vite.config.ts b/web/vite.config.ts index 739de4d..9f1f5f7 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -1,10 +1,14 @@ import preact from '@preact/preset-vite'; import { defineConfig } from 'vite'; -// https://vitejs.dev/config/ export default defineConfig({ - plugins: [preact()], - server: { - cors: true - } -}); + base: '/public', + plugins: [preact()], + server: { + cors: true + }, + build: { + outDir: '../public', + emptyOutDir: true + } +}); \ No newline at end of file