diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 index 2c66ec6..bfef380 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Attribution-ShareAlike 4.0 International +Attribution-NonCommercial-ShareAlike 4.0 International ======================================================================= @@ -54,18 +54,18 @@ exhaustive, and do not form part of our licenses. ======================================================================= -Creative Commons Attribution-ShareAlike 4.0 International Public -License +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International +Public License By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons -Attribution-ShareAlike 4.0 International Public License ("Public -License"). To the extent this Public License may be interpreted as a -contract, You are granted the Licensed Rights in consideration of Your -acceptance of these terms and conditions, and the Licensor grants You -such rights in consideration of benefits the Licensor receives from -making the Licensed Material available under these terms and -conditions. +Attribution-NonCommercial-ShareAlike 4.0 International Public License +("Public License"). To the extent this Public License may be +interpreted as a contract, You are granted the Licensed Rights in +consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the +Licensor receives from making the Licensed Material available under +these terms and conditions. Section 1 -- Definitions. @@ -84,7 +84,7 @@ Section 1 -- Definitions. and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. - c. BY-SA Compatible License means a license listed at + c. BY-NC-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses, approved by Creative Commons as essentially the equivalent of this Public License. @@ -108,7 +108,7 @@ Section 1 -- Definitions. g. License Elements means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this - Public License are Attribution and ShareAlike. + Public License are Attribution, NonCommercial, and ShareAlike. h. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public @@ -122,7 +122,15 @@ Section 1 -- Definitions. j. Licensor means the individual(s) or entity(ies) granting rights under this Public License. - k. Share means to provide material to the public by any means or + k. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + l. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material @@ -130,13 +138,13 @@ Section 1 -- Definitions. public may access the material from a place and at a time individually chosen by them. - l. Sui Generis Database Rights means rights other than copyright + m. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. - m. You means the individual or entity exercising the Licensed Rights + n. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. @@ -150,9 +158,10 @@ Section 2 -- Scope. exercise the Licensed Rights in the Licensed Material to: a. reproduce and Share the Licensed Material, in whole or - in part; and + in part, for NonCommercial purposes only; and - b. produce, reproduce, and Share Adapted Material. + b. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public @@ -220,7 +229,9 @@ Section 2 -- Scope. Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly - reserves any right to collect such royalties. + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. Section 3 -- License Conditions. @@ -265,7 +276,6 @@ following conditions. reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. - 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. @@ -277,7 +287,7 @@ following conditions. 1. The Adapter's License You apply must be a Creative Commons license with the same License Elements, this version or - later, or a BY-SA Compatible License. + later, or a BY-NC-SA Compatible License. 2. You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition @@ -297,7 +307,8 @@ apply to Your use of the Licensed Material: a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial - portion of the contents of the database; + portion of the contents of the database for NonCommercial purposes + only; b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database @@ -404,7 +415,6 @@ Section 8 -- Interpretation. that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. - ======================================================================= Creative Commons is not a party to its public diff --git a/README.md b/README.md index ad13b5d..874da1f 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,35 @@ Kamu bisa langsung fork aja repo ini, atau bisa tekan tombol dibawah ini (jangan ``` https://api.isan.eu.org/nickname ``` +## Metode Request +API ini mendukung metode GET dan POST. +1. Metode GET + +Anda dapat mengirimkan parameter langsung melalui URL. +``` +/ml?id=1114917746&server=13486 +``` +2. Metode POST + +Anda juga dapat mengirimkan data melalui body request dengan `Content-Type` berupa `application/json` atau `application/x-www-form-urlencoded`. Ini berguna untuk menyembunyikan parameter dari URL. + +Contoh (`application/json`): +```sh +curl -X POST 'https://api.isan.eu.org/nickname/ml' \ +-H 'Content-Type: application/json' \ +-d '{ + "id": "1114917746", + "server": "13486" +}' +``` +Contoh (`application/x-www-form-urlencoded`): +```sh +curl -X POST 'https://api.isan.eu.org/nickname/ml' \ +-H 'Content-Type: application/x-www-form-urlencoded' \ +-d 'id=1114917746&server=13486' +``` ## Output -application/json; charset=utf-8 ([RFC4627](https://datatracker.ietf.org/doc/html/rfc4627)) +application/json ([RFC4627](https://datatracker.ietf.org/doc/html/rfc4627)) ```ts interface Result { success: boolean; @@ -117,4 +144,4 @@ Contoh penggunaan `?decode=true` ## Monitoring API monitoring [UptimeRobot](https://stats.uptimerobot.com/s9axzR77Fm) # Copyright -© Projek ini dibawah lisensi: [CC BY-NC 4.0](https://creativecommons.org/licenses/by-nc/4.0/), tidak terafiliasi dengan Codashop. +© Projek ini dibawah lisensi: [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/), tidak terafiliasi dengan Codashop. diff --git a/src/handler.ts b/src/handler.ts index 9dc1bb3..ad40e28 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -1,30 +1,30 @@ -import { allowedMethod, timeNow } from './utils' +import { allowedMethod, parseRequest, timeNow } from './utils' import serveResult from './helpers' export default async function checkCache(request: Request): Promise { - const now = timeNow() + const now = Date.now() if (allowedMethod.indexOf(request.method) === -1) { - return new Response(JSON.stringify({ + return Response.json({ success: false, message: 'Method not allowed' - }), { + }, { status: 405, headers: { 'Allow': allowedMethod.join(', '), 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': allowedMethod.join(', '), - 'Content-Type': 'application/json; charset=utf-8', 'X-Powered-By': '@ihsangan/valid' } }) } + let url = await parseRequest(request) let cache = caches.default - let response = await cache.match(request.url) + let response = await cache.match(url) if (!response) { - response = await serveResult(request) - await cache.put(request.url, response.clone()) + response = await serveResult(url) + await cache.put(url, response.clone()) } response = new Response(response.body, response) - response.headers.set('X-Response-Time', timeNow() - now) + response.headers.set('X-Response-Time', Date.now() - now) return response } \ No newline at end of file diff --git a/src/helpers.ts b/src/helpers.ts index 94308d7..9c3085d 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -1,32 +1,30 @@ -import { getUrl, Result, allowedMethod } from './utils' +import { getParams, Result, allowedMethod } from './utils' import callAPI from './routing' -export default async function serveResult(request: Request): Promise { - const dc = getUrl(request).searchParams.get('decode') - let code = 200 - let result: Result = await callAPI(request); +export default async function serveResult(url: string): Promise { + const { decode } = getParams(url) + let status = 200 + let result: Result = await callAPI(url) if (result.name) { result.name = result.name.replace(/\u002B/g, '%20') - if (dc === null || dc === 'true' || dc !== 'false') { + if (decode === null || decode === 'true' || decode !== 'false') { result.name = decodeURIComponent(result.name) } } if (result.message === 'Bad request') { - code = 400 + status = 400 } if (result.message === 'Not found') { - code = 404 + status = 404 } - const response = new Response(JSON.stringify(result), { - status: code, + return Response.json(result, { + status, headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': allowedMethod.join(', '), 'Access-Control-Expose-Headers': '*', 'Cache-Control': 'public, max-age=30, s-maxage=43200, proxy-revalidate, immutable', - 'Content-Type': 'application/json; charset=utf-8', 'X-Powered-By': '@ihsangan/valid' } }) - return response } \ No newline at end of file diff --git a/src/routing.ts b/src/routing.ts index 551857b..6692ddb 100644 --- a/src/routing.ts +++ b/src/routing.ts @@ -1,16 +1,13 @@ -import { getUrl, Result } from './utils' +import { getParams, Result } from './utils' import * as router from './router' -export default async function callAPI(request: Request): Promise { - const url = getUrl(request) - const path = url.pathname - const params = url.searchParams - const id = params.get('id') - const server = params.get('zone') || params.get('server') +export default async function callAPI(url: string): Promise { + let { path, id, server, zone} = getParams(url) + server = server || zone if (!id) { return { success: false, - message: 'Bad request' + message: 'Bad request' } } try { diff --git a/src/utils.ts b/src/utils.ts index 0e4823d..8707f46 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,13 +1,48 @@ -export const allowedMethod = ['GET', 'HEAD'] - -export function getUrl(request: Request): URL { - return new URL(request.url) -} +export const allowedMethod = ['GET', 'HEAD', 'POST'] export function timeNow(): number { return Date.now() } +export async function parseRequest(request: Request): Promise { + let url = new URL(request.url) + if (request.method === 'POST') { + const contentType = request.headers.get('content-type') + let data: { [key: string]: string | null } = {} + try { + if (contentType && contentType.includes('application/json')) { + data = await request.json() + } else if (contentType && contentType.includes('application/x-www-form-urlencoded')) { + const formData = await request.formData() + for (const [key, value] of formData.entries()) { + data[key] = value + } + } else { + return url.toString() + } + for (const key in data) { + url.searchParams.set(key, data[key]) + } + return url.toString() + } catch (error) { + return url.toString() + } + } + return url.toString() +} + +export function getParams(inputUrl: string): Params { + const url = new URL(inputUrl) + const urlParams = url.searchParams + const params: Params = { + path: url.pathname + } + for (const [key, value] of urlParams.entries()) { + params[key] = value + } + return params +} + export async function hitCoda(body: string): Promise { const response = await fetch('https://order-sg.codashop.com/initPayment.action', { method: 'POST', @@ -19,11 +54,19 @@ export async function hitCoda(body: string): Promise { return await response.json() } +interface Params{ + path: string + id?: string + server?: string + zone?: string + decode?: string +} + export interface Result { success: boolean game?: string id?: number | string - server?: string | number, + server?: string | number name?: string message?: string } \ No newline at end of file