diff --git a/api/dist/bundle.js b/api/dist/bundle.js index f78e72e..7efdb4b 100644 --- a/api/dist/bundle.js +++ b/api/dist/bundle.js @@ -1 +1 @@ -!function(t){var e={};function n(r){if(e[r])return e[r].exports;var u=e[r]={i:r,l:!1,exports:{}};return t[r].call(u.exports,u,u.exports,n),u.l=!0,u.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var u in t)n.d(r,u,function(e){return t[e]}.bind(null,u));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){"use strict";n.r(e);n(1);var r,u=async function(t,e,{ttl:n,extra:r}={}){var u;return u=await a(t,e,{ttl:n,extra:r}),[d(u.status),await async function(){try{return await u.json()}catch(t){return t,null}}()]},a=function(t,e,{ttl:n,extra:r}={}){return null==n&&(n=60),null==r&&(r={}),fetch(t,{method:e,cf:n>0?{cacheTtl:n}:void 0,headers:{"Content-Type":"application/json","Accept-Encoding":"gzip"}}.merge(r))},i=function(t,e={}){return a(t,"GET",e)},o=function(t,e={}){return u(t,"GET",e)};r=function(t,e){return new Response(JSON.stringify(t,void 0,2),{status:e,headers:{"Content-Type":"application/json","Accept-Encoding":"gzip"}})};var s,c=function(t=500,e="Internal Error",n=null){return r({status:t,message:e+(n?` - ${n}`:"")},t)},l=function(t=null){return c(404,"Not Found",t)},f=function(t=null){return c(400,"Invalid Request",t)},d=function(t){switch(t){case 200:return null;case 204:return l();case 400:return f();case 429:return function(t=null){return c(429,"Too Many Requests",t)}();default:return c()}};s=function(t){return(t.toInt(7)^t.toInt(15)^t.toInt(23)^t.toInt(31))%2!=0};var p,m=async function(t){var e,n,r,u;return(n=t.asUuid())?[null,n]:(u=t.asUsername())?([e,r]=await function(t,e=-1){return o(`https://api.mojang.com/users/profiles/minecraft/${t}${e>=0?`?at=${e}`:""}`)}(u),[e,null!=r?r.id:void 0]):[f(`Malformed UUID or Username '${t}'`),null]},h=async function(t){var e,n,u,a,i,c,l;return[u,n]=await Promise.all([async function(t){var e,n,r;return[e,n]=await o(`https://sessionserver.mojang.com/session/minecraft/profile/${t}`),e||((r=JSON.parse(atob(n.properties[0].value)).textures).isEmpty()&&(r=s(t)?{SKIN:{url:"http://textures.minecraft.net/texture/83cee5ca6afcdb171285aa00e8049c297b2dbeba0efb8ff970a5677a1b644032",metadata:{model:"slim"}}}:{SKIN:{url:"http://textures.minecraft.net/texture/dc1c77ce8e54925ab58125446ec53b0cdd3d0ca3db273eb908d5482787ef4016"}}),n.textures=r),[e,n]}(t),function(t){return o(`https://api.mojang.com/user/profiles/${t}/names`)}(t)]),(e=u[0]||n[0])?[e,null]:(u=u[1])&&(n=n[1])?[null,function(t){return r(t,200)}({uuid:t=u.id,uuid_dashed:t.asUuid({dashed:!0}),username:u.name,username_history:n.map(function(t){var e;return{username:t.name,changed_at:null!=(e=t.changedToAt)?e.asDate():void 0}}),textures:{skin:null!=(a=u.textures.SKIN)?a.url:void 0,cape:null!=(i=u.textures.CAPE)?i.url:void 0,slim:"slim"===(null!=(c=u.textures.SKIN)&&null!=(l=c.metadata)?l.model:void 0)},cached_at:new Date})]:[f(`Invalid UUID '${t}'`),null]};addEventListener("fetch",function(t){return t.respondWith(p(t.request))}),p=async function(t){var e,n,r,u,a,o;return[e,a,u,r]=t.url.split("/").slice(3,7),"minecraft"===e&&null!=u&&([n,u]=await m(u),n||("user"===a?[n,o]=await h(u):"avatar"===a&&(o=i(`https://us-central1-stratus-197318.cloudfunctions.net/avatar/${u}/${r}`,{ttl:86400})))),n||o||l("Unknown Route")}},function(t,e){var n,r;String.prototype.toInt=function(t=0){var e;return(e=this.charCodeAt(t))>=97?e-87:e-48},Object.prototype.merge=function(t){return Object.assign({},this,t)},String.prototype.asUuid=function({dashed:t}={}){var e,n;if(null==t&&(t=!1),e=r.exec(this))return n=e.slice(1).join(""),t?[n.substring(0,8),n.substring(8,12),n.substring(12,16),n.substring(16,20),n.substring(20,32)].join("-"):n},r=/^([0-9a-f]{8})(?:-|)([0-9a-f]{4})(?:-|)(4[0-9a-f]{3})(?:-|)([0-9a-f]{4})(?:-|)([0-9a-f]{12})$/i,String.prototype.asUsername=function(){return!!n.test(this)&&this},n=/^[0-9A-Za-z_]{1,16}$/i,String.prototype.asJson=function(){try{return JSON.parse(this)}catch(t){return!1}},Number.prototype.asDate=function(){return new Date(Math.floor(this))},Object.prototype.isEmpty=function(){return 0===Object.keys(this).length}}]); \ No newline at end of file +!function(t){var e={};function n(r){if(e[r])return e[r].exports;var u=e[r]={i:r,l:!1,exports:{}};return t[r].call(u.exports,u,u.exports,n),u.l=!0,u.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var u in t)n.d(r,u,function(e){return t[e]}.bind(null,u));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){"use strict";n.r(e);n(1);var r,u=async function(t,e,{ttl:n,extra:r}={}){var u;return u=await a(t,e,{ttl:n,extra:r}),[d(u.status),await async function(){try{return await u.json()}catch(t){return t,null}}()]},a=function(t,e,{ttl:n,extra:r}={}){return null==n&&(n=60),null==r&&(r={}),fetch(t,{method:e,cf:n>0?{cacheTtl:n}:void 0,headers:{"Content-Type":"application/json","Accept-Encoding":"gzip"}}.merge(r))},o=function(t,e={}){return a(t,"GET",e)},i=function(t,e={}){return u(t,"GET",e)};r=function(t,e){return new Response(JSON.stringify(t,void 0,2),{status:e,headers:{"Content-Type":"application/json","Accept-Encoding":"gzip"}})};var s,c=function(t=500,e="Internal Error",n=null){return r({status:t,message:e+(n?` - ${n}`:"")},t)},l=function(t=null){return c(404,"Not Found",t)},f=function(t=null){return c(400,"Invalid Request",t)},d=function(t){switch(t){case 200:return null;case 204:return l();case 400:return f();case 429:return function(t=null){return c(429,"Too Many Requests",t)}();default:return c()}};s=function(t){return(t.toInt(7)^t.toInt(15)^t.toInt(23)^t.toInt(31))%2!=0};var p,m=async function(t){var e,n,r,u;return(n=t.asUuid())?[null,n]:(u=t.asUsername())?([e,r]=await function(t,e=-1){return i(`https://api.mojang.com/users/profiles/minecraft/${t}${e>=0?`?at=${e}`:""}`)}(u),[e,null!=r?r.id:void 0]):[f(`Malformed UUID or Username '${t}'`),null]},h=async function(t){var e,n,u,a,o,c,l;return[u,n]=await Promise.all([async function(t){var e,n,r;return[e,n]=await i(`https://sessionserver.mojang.com/session/minecraft/profile/${t}`),e||((r=JSON.parse(atob(n.properties[0].value)).textures).isEmpty()&&(r=s(t)?{SKIN:{url:"http://textures.minecraft.net/texture/83cee5ca6afcdb171285aa00e8049c297b2dbeba0efb8ff970a5677a1b644032",metadata:{model:"slim"}}}:{SKIN:{url:"http://textures.minecraft.net/texture/dc1c77ce8e54925ab58125446ec53b0cdd3d0ca3db273eb908d5482787ef4016"}}),n.textures=r),[e,n]}(t),function(t){return i(`https://api.mojang.com/user/profiles/${t}/names`)}(t)]),(e=u[0]||n[0])?[e,null]:(u=u[1])&&(n=n[1])?[null,function(t){return r(t,200)}({uuid:t=u.id,uuid_dashed:t.asUuid({dashed:!0}),username:u.name,username_history:n.map(function(t){var e;return{username:t.name,changed_at:null!=(e=t.changedToAt)?e.asDate():void 0}}),textures:{skin:null!=(a=u.textures.SKIN)?a.url:void 0,cape:null!=(o=u.textures.CAPE)?o.url:void 0,slim:"slim"===(null!=(c=u.textures.SKIN)&&null!=(l=c.metadata)?l.model:void 0)},cached_at:new Date})]:[f(`Invalid UUID '${t}'`),null]},v=function(t="Steve",e=8){return function(t){return o(t=new URL(t),{extra:{cf:{resolveOverride:t.hostname}}})}(`https://avatar.ashcon.app/${t}/${e}`)};addEventListener("fetch",function(t){return t.respondWith(p(t.request))}),p=async function(t){var e,n,r,u,a,o;return[e,a,u,r]=t.url.split("/").slice(3,7),"minecraft"===e&&null!=u&&([n,u]=await m(u),n||("user"===a?[n,o]=await h(u):"avatar"===a&&(o=v(u,r)))),n||o||l("Unknown Route")}},function(t,e){var n,r;String.prototype.toInt=function(t=0){var e;return(e=this.charCodeAt(t))>=97?e-87:e-48},Object.prototype.merge=function(t){return Object.assign({},this,t)},String.prototype.asUuid=function({dashed:t}={}){var e,n;if(null==t&&(t=!1),e=r.exec(this))return n=e.slice(1).join(""),t?[n.substring(0,8),n.substring(8,12),n.substring(12,16),n.substring(16,20),n.substring(20,32)].join("-"):n},r=/^([0-9a-f]{8})(?:-|)([0-9a-f]{4})(?:-|)(4[0-9a-f]{3})(?:-|)([0-9a-f]{4})(?:-|)([0-9a-f]{12})$/i,String.prototype.asUsername=function(){return!!n.test(this)&&this},n=/^[0-9A-Za-z_]{1,16}$/i,String.prototype.asJson=function(){try{return JSON.parse(this)}catch(t){return!1}},Number.prototype.asDate=function(){return new Date(Math.floor(this))},Object.prototype.isEmpty=function(){return 0===Object.keys(this).length}}]); \ No newline at end of file diff --git a/api/src/api.coffee b/api/src/api.coffee index 896371b..0216c01 100644 --- a/api/src/api.coffee +++ b/api/src/api.coffee @@ -1,4 +1,4 @@ -import { json, error, invalidRequest } from "./http" +import { json, error, invalidRequest, redirect } from "./http" import { usernameToUuid, uuidToProfile, uuidToUsernameHistory } from "./mojang" # If given a username, find its UUID, otherwise @@ -40,3 +40,11 @@ export user = (id) -> cached_at: new Date()] else [invalidRequest("Invalid UUID '#{id}'"), null] + +# Redirect to the avatar service to render the face of a user. +# +# @param {string} id - UUID of the user. +# @param {integer} size - Size in pixels of the avatar. +# @returns {promise} - Avatar response as a PNG. +export avatar = (id = "Steve", size = 8) -> + redirect("https://avatar.ashcon.app/#{id}/#{size}") diff --git a/api/src/index.coffee b/api/src/index.coffee index 11b52bd..e44a8db 100644 --- a/api/src/index.coffee +++ b/api/src/index.coffee @@ -1,6 +1,6 @@ import "./util" import { notFound, get } from "./http" -import { uuid, user } from "./api" +import { uuid, user, avatar } from "./api" addEventListener("fetch", (event) -> event.respondWith(route(event.request))) @@ -13,5 +13,5 @@ route = (request) -> if method == "user" [err, res] = await user(id) else if method == "avatar" - res = get("https://us-central1-stratus-197318.cloudfunctions.net/avatar/#{id}/#{extra}", ttl: 86400) + res = avatar(id, extra) err || res || notFound("Unknown Route")