generated from kawarimidoll/deno-dev-template
-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
server.ts
128 lines (109 loc) · 4.09 KB
/
server.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { getContributions, totalMsg } from "./contributions.ts";
import { outdent } from "./deps.ts";
// cache one hour
const CACHE_MAX_AGE = 3600;
function getPathExtension(request: Request): string {
const { pathname } = new URL(request.url);
const split = pathname.split(".");
return split.length > 1 ? split[split.length - 1] : "";
}
async function handleRequest(request: Request) {
const { pathname, searchParams, host } = new URL(request.url);
if (pathname === "/") {
return [
"Welcome to deno-github-contributions-api!",
`Access to ${host}/[username] to get your contributions data.`,
].join("\n");
}
const paths = pathname.split("/");
if (paths.length > 2) {
throw new Error(
`'${request.url}' is invalid path. Access to ${host}/[username].`,
);
}
const username = paths[1].replace(/\..*$/, "");
const ext = getPathExtension(request);
const toYmd = searchParams.get("to") ?? null;
const fromYmd = searchParams.get("from") ?? null;
const from = fromYmd ? new Date(fromYmd).toISOString() : undefined;
const to = toYmd ? new Date(toYmd).toISOString() : undefined;
const contributions = await getContributions(
username,
Deno.env.get("GH_READ_USER_TOKEN") || "",
{ from, to },
);
const scheme = searchParams.get("scheme") ?? "github";
const pixel = searchParams.get("pixel") ?? undefined;
const noTotal = searchParams.get("no-total") == "true";
const noLegend = searchParams.get("no-legend") == "true";
const flat = searchParams.get("flat") == "true";
const invert = searchParams.get("invert") == "true";
const fontColor = searchParams.get("font-color") ?? "#000";
const frame = searchParams.get("frame") ?? "none";
const bg = searchParams.get("bg") ?? "none";
if (ext === "json") {
return contributions.toJson({ flat });
}
if (ext === "term") {
return contributions.toTerm({ scheme, pixel, noTotal, noLegend, invert });
}
if (ext === "text") {
return contributions.toText({ noTotal });
}
if (ext === "svg") {
return contributions.toSvg({
scheme,
noTotal,
noLegend,
frame,
bg,
fontColor,
});
}
return outdent`
${totalMsg(contributions.totalContributions)}.
Use extensions like as '${host}/${username}.text'.
- .json : return data as a json
- .term : return data as a colored pixels graph (works in the terminal with true color)
- .text : return data as a table-styled text
- .svg : return data as a svg image
You can use other parameters. Each of them works on specific extensions.
- no-total=true : remove total contributions count (term/text/svg)
- no-legend=true : remove legend (term/svg)
- invert=true : change the background colors instead of the foreground colors (term)
- flat=true : return contributions as one-dimensional array (json)
- scheme=[name] : use specific color scheme (term/svg)
- pixel=[char] : use the character as pixels, URL encoding is required (term)
- frame=[color] : use the color as a frame of image (svg)
- bg=[color] : use the color as a background of image (svg)
- font-color=[color] : use the color as a font color (svg)
- from=[yyyy-mm-dd] : get contributions from the date (term/text/svg/json)
- to=[yyyy-mm-dd] : get contributions to the date (term/text/svg/json)
Color parameters allows hex color string without # like '123abc'.
`;
}
Deno.serve(async (request: Request) => {
const ext = getPathExtension(request);
const type = {
json: "application/json",
svg: "image/svg+xml",
}[ext] || "text/plain";
const headers = {
"Content-Type": `${type}; charset=utf-8`,
"Cache-Control": `public, max-age=${CACHE_MAX_AGE}`,
"Access-Control-Allow-Origin": "*",
};
try {
const body = await handleRequest(request);
return (new Response(body, { headers }));
} catch (error) {
console.error(error);
const body = ext == "json"
? JSON.stringify({ error: `${error}` })
: `${error}`;
return (new Response(body, {
status: 400,
headers,
}));
}
});