-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
119 lines (102 loc) · 3.54 KB
/
server.js
File metadata and controls
119 lines (102 loc) · 3.54 KB
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
const express = require("express");
const cors = require("cors");
const fetch = require("node-fetch");
// NOTE: The original Firebase Admin + /summary endpoint has been removed
// because this server is now focused on proxying external APIs for the
// front-end (Code_Class) to avoid CORS issues.
const app = express();
app.use(cors());
app.use(express.json());
// Helper to mimic a browser
const fetchWithUA = async (url) => {
return fetch(url, {
headers: {
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
},
});
};
// ---------- Proxy endpoints for Code_Class ----------
// LeetCode proxy (uses public Lydia LeetCode API to simplify)
app.post("/code-class/leetcode", async (req, res) => {
try {
const { username } = req.body || {};
if (!username) {
return res.status(400).json({ error: "username is required" });
}
// Lydia's LeetCode API (no auth, community maintained)
const upstream = await fetchWithUA(
`https://leetcode-api.herokuapp.com/username/${encodeURIComponent(
username
)}`
);
if (!upstream.ok) {
console.error("LeetCode upstream error:", upstream.status);
return res
.status(502)
.json({ error: "Upstream LeetCode API error", status: upstream.status });
}
const data = await upstream.json();
res.json(data);
} catch (e) {
console.error("LeetCode proxy error:", e);
res.status(500).json({ error: "Failed to proxy LeetCode" });
}
});
// CodeChef profile proxy
app.get("/code-class/codechef/:username", async (req, res) => {
try {
const { username } = req.params;
const upstream = await fetchWithUA(
`https://codechef-api.vercel.app/${encodeURIComponent(username)}`
);
const data = await upstream.json();
res.json(data);
} catch (e) {
console.error("CodeChef proxy error:", e);
res.status(500).json({ error: "Failed to proxy CodeChef" });
}
});
// GeeksforGeeks profile page proxy (HTML)
app.get("/code-class/gfg/:username", async (req, res) => {
try {
const { username } = req.params;
const upstream = await fetchWithUA(
`https://www.geeksforgeeks.org/user/${encodeURIComponent(
username
)}`
);
// GFG profile URL is /user/USERNAME (sometimes /user/USERNAME/)
if (!upstream.ok) {
console.error("GFG upstream error:", upstream.status);
if (upstream.status === 404) return res.status(404).send("GFG User not found");
return res.status(upstream.status).send("GFG Upstream Error");
}
const text = await upstream.text();
res.type("text/plain").send(text);
} catch (e) {
console.error("GFG proxy error:", e);
res.status(500).send("Failed to proxy GFG");
}
});
// HackerEarth profile page proxy (HTML)
app.get("/code-class/hackerearth/:username", async (req, res) => {
try {
const { username } = req.params;
const upstream = await fetchWithUA(
`https://www.hackerearth.com/@${encodeURIComponent(username)}`
);
if (!upstream.ok) {
console.error("HackerEarth upstream error:", upstream.status);
return res.status(upstream.status).send("HackerEarth Upstream Error");
}
const text = await upstream.text();
res.type("text/plain").send(text);
} catch (e) {
console.error("HackerEarth proxy error:", e);
res.status(500).send("Failed to proxy HackerEarth");
}
});
const PORT = 4000;
app.listen(PORT, () => console.log(`Code_Class proxy server running on ${PORT}`));