tangled
alpha
login
or
join now
ovyerus.com
/
astro-shortlinks
1
fork
atom
Automatically create shortlinks for your Astro site
1
fork
atom
overview
issues
pulls
pipelines
feat: chhoto-url shortlinker
ovyerus.com
3 months ago
c103f38b
35c69e3b
verified
This commit was signed with the committer's
known signature
.
ovyerus.com
SSH Key Fingerprint:
SHA256:mXbp9WNBIT0nRNe28t2hrxfSwnSX7UBeW2DVlIyf0uw=
+120
1 changed file
expand all
collapse all
unified
split
src
chhoto-url.ts
+120
src/chhoto-url.ts
···
1
1
+
import type { AstroIntegrationLogger } from "astro";
2
2
+
import type { Shortlinker } from "./types.js";
3
3
+
4
4
+
interface ChhotoUrlErrorResponse {
5
5
+
success: false;
6
6
+
error: true;
7
7
+
reason: string;
8
8
+
}
9
9
+
10
10
+
interface ChhotoUrlNewResponse {
11
11
+
success: true;
12
12
+
error: false;
13
13
+
shorturl: string;
14
14
+
expiry_time: number;
15
15
+
}
16
16
+
17
17
+
interface ChhotoUrlEditResponse {
18
18
+
success: true;
19
19
+
error: false;
20
20
+
reason: string;
21
21
+
}
22
22
+
23
23
+
interface ChhotoUrlEntry {
24
24
+
shortlink: string;
25
25
+
longlink: string;
26
26
+
hits: number;
27
27
+
expiry_time: number;
28
28
+
}
29
29
+
30
30
+
type ChhotoUrlAllResponse = ChhotoUrlEntry[];
31
31
+
32
32
+
export interface ChhotoUrlOptions {
33
33
+
domain: string;
34
34
+
apiKey?: string;
35
35
+
resetHits?: boolean;
36
36
+
}
37
37
+
38
38
+
/**
39
39
+
* Shortlinker to create links on a https://github.com/SinTan1729/chhoto-url instance.
40
40
+
*/
41
41
+
export const chhotoUrl = ({
42
42
+
domain,
43
43
+
apiKey,
44
44
+
resetHits = false,
45
45
+
}: ChhotoUrlOptions): Shortlinker => {
46
46
+
return {
47
47
+
name: "chhoto-url",
48
48
+
async run($mappings, logger) {
49
49
+
const handleError = async (response: Response, action: string) => {
50
50
+
if (response.headers.get("Content-Type") === "application/json") {
51
51
+
const { reason }: ChhotoUrlErrorResponse = await response.json();
52
52
+
logger.error(`Failed to ${action}: ${reason}`);
53
53
+
} else {
54
54
+
const error = await response.text();
55
55
+
logger.error(
56
56
+
`Failed to ${action}. Status: ${response.status}, ${error}`
57
57
+
);
58
58
+
}
59
59
+
60
60
+
return false;
61
61
+
};
62
62
+
63
63
+
const headers: Record<string, string> = apiKey
64
64
+
? { "X-API-Key": apiKey }
65
65
+
: {};
66
66
+
// chhoto-url doesn't allow slashes at the start of shortlinks, so clean
67
67
+
// it up for users.
68
68
+
const mappings = $mappings.map(({ longlink, shortlink }) => ({
69
69
+
longlink,
70
70
+
shortlink: shortlink.replace(/^\//, ""),
71
71
+
}));
72
72
+
73
73
+
const listRes = await fetch(new URL("/api/all", domain), { headers });
74
74
+
75
75
+
if (listRes.status === 401) {
76
76
+
logger.error("Provided apiKey is either missing or incorrect.");
77
77
+
return false;
78
78
+
} else if (!listRes.ok) {
79
79
+
const err = await listRes.text();
80
80
+
logger.error(`Failed to list all shortlinks: ${err}`);
81
81
+
return false;
82
82
+
}
83
83
+
84
84
+
const list: ChhotoUrlAllResponse = await listRes.json();
85
85
+
// Find ones that need to be updated because the longlink has changed.
86
86
+
const existingLinksToUpdate = mappings.filter((map) =>
87
87
+
list.find(
88
88
+
(item) =>
89
89
+
item.shortlink === map.shortlink && item.longlink !== map.longlink
90
90
+
)
91
91
+
);
92
92
+
// Find new ones that need to be created.
93
93
+
const newLinks = mappings.filter(
94
94
+
(map) => !list.find((item) => item.shortlink === map.shortlink)
95
95
+
);
96
96
+
97
97
+
for (const link of newLinks) {
98
98
+
const newRes = await fetch(new URL("/api/new", domain), {
99
99
+
method: "POST",
100
100
+
headers: { ...headers, "Content-Type": "application/json" },
101
101
+
body: JSON.stringify(link),
102
102
+
});
103
103
+
104
104
+
if (!newRes.ok)
105
105
+
return handleError(newRes, `create shortlink "${link.shortlink}"`);
106
106
+
}
107
107
+
108
108
+
for (const link of existingLinksToUpdate) {
109
109
+
const editRes = await fetch(new URL("/api/edit", domain), {
110
110
+
method: "PUT",
111
111
+
headers: { ...headers, "Content-Type": "application/json" },
112
112
+
body: JSON.stringify({ ...link, reset_hits: resetHits }),
113
113
+
});
114
114
+
115
115
+
if (!editRes.ok)
116
116
+
return handleError(editRes, `edit shortlink "${link.shortlink}"`);
117
117
+
}
118
118
+
},
119
119
+
};
120
120
+
};