hooh / index.js
Ruloaooa's picture
Update index.js
1b8d4ae verified
const express = require("express");
const mongoose = require("mongoose");
const crypto = require("crypto");
const path = require("path");
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, "public")));
app.use(express.json({ limit: "5mb" }));
// =====================
// πŸ”— MongoDB Connect
// =====================
mongoose.connect("mongodb+srv://zennn:Khoirul78@cluster0.ubprd.mongodb.net/?appName=Cluster0")
.then(() => console.log("βœ… MongoDB Connected"))
.catch(err => console.log(err));
// =====================
// πŸ”‘ TOKEN GENERATOR
// =====================
function generateUID() {
return Math.floor(1000000 + Math.random() * 9000000);
}
function generateToken(uid) {
return crypto
.createHash("sha256")
.update(uid + ":" + Date.now())
.digest("hex");
}
// =====================
// πŸ“¦ PLAYER MODEL
// =====================
const PlayerSchema = new mongoose.Schema({
uid: Number,
open_id: String,
game_server_id: { type: String, default: 1 },
nickname: String,
device_id: String,
token: String,
banned: { type: Boolean, default: false },
account_type: { type: Number, default: 0 },
region: { type: String, default: "BR" },
level: { type: Number, default: 1 },
exp: { type: Number, default: 0 },
coins: { type: Number, default: 0 },
gems: { type: Number, default: 0 },
ranking_points: Number,
rank: Number,
wallet: { type: Object, default: {} },
profile: { type: Object, default: {} },
selected_items: { type: Object, default: {} },
backpack: { type: Object, default: {} },
friends: { type: Array, default: [] },
requests: { type: Array, default: [] },
clan: { type: Object, default: {} },
client_version: String
}, { timestamps: true });
const Player = mongoose.model("Player", PlayerSchema);
app.use((req, res, next) => {
const now = new Date().toISOString();
console.log("================================");
console.log(`[${now}] ${req.method} ${req.url}`);
console.log("Headers:", req.headers);
console.log("Query :", req.query);
console.log("Body :", req.body);
console.log("================================");
next();
});
app.use((req, res, next) => {
let data = "";
req.on("data", chunk => data += chunk);
req.on("end", () => {
if (data) console.log("RAW BODY:", data);
});
next();
});
//Guest test===
function genUID() {
return Math.floor(1000000 + Math.random() * 9000000);
}
function genToken(uid) {
return `TOKEN_${uid}_${Date.now()}`;
}
app.post("/oauth/guest/register", async (req, res) => {
try {
let client_version =
req.body?.client_version ||
req.headers["x-client-version"] ||
req.headers["client-version"] ||
"2.19.2";
const device_id =
req.headers["x-device-id"] ||
req.headers["device-id"] ||
req.headers["x-udid"] ||
req.headers["open-udid"] ||
req.headers["x-open-udid"] ||
crypto
.createHash("md5")
.update(req.ip + req.headers["user-agent"])
.digest("hex");
console.log("REGISTER HIT:", device_id);
if (!device_id) {
return res.status(400).json({ message: "device_id required" });
}
let user = await Player.findOne({ device_id });
let uid = await generateUID();
if (!user) {
user = await Player.create({
uid, // sementara aman
open_id: "guest_" + uid,
nickname: "KalidadeMob",
device_id,
token: generateToken(uid),
level: 100,
exp: 25000000,
coins: 999999,
gems: 5600,
ranking_points: 1000,
rank: 1,
region: "BR",
game_server_id: "GS_1",
client_version
});
console.log("USER CREATED:", user.uid);
}
res.json({
success: true,
uid: user.uid,
open_id: user.open_id,
access_token: user.token,
token_type: "Bearer",
expires_in: 86400
});
} catch (err) {
console.error("REGISTER ERROR:", err);
res.status(500).json({
success: false,
error: err.message
});
}
});
app.all("/oauth/guest/token/grant",
express.urlencoded({ extended: false }),
async (req, res) => {
try {
const uid =
req.body?.uid ||
req.query?.uid ||
req.headers["x-uid"];
const device_id =
req.headers["x-device-id"] ||
req.query?.device_id;
const player = uid
? await Player.findOne({ uid })
: await Player.findOne({ device_id });
if (!player) {
return res.status(200).json({
error: "invalid_guest"
});
}
// ⚠️ JANGAN GENERATE TOKEN BARU
const token = player.token;
// πŸ”₯ HEADER INI PENTING
res.setHeader("Content-Type", "application/json");
res.setHeader("Cache-Control", "no-store");
return res.status(200).json({
access_token: token,
refresh_token: token,
token_type: "Bearer",
expires_in: 86400,
scope: "all",
uid: player.uid
});
} catch (e) {
console.error("TOKEN GRANT FATAL:", e);
return res.status(200).json({
error: "server_error"
});
}
});
app.all("/oauth/token/inspect", async (req, res) => {
const token =
req.body?.token ||
req.query?.token ||
req.headers["authorization"]?.replace("Bearer ", "");
const player = await Player.findOne({ token });
if (!player) {
return res.json({ active: false });
}
res.json({
active: true,
uid: player.uid,
client_id: "freefire",
username: player.open_id,
token_type: "Bearer",
scope: ["all"],
authorities: ["ROLE_USER"],
exp: Math.floor(Date.now() / 1000) + 86400
});
});
app.get("/oauth/user/info/get", async (req, res) => {
const token = req.headers["authorization"]?.replace("Bearer ", "");
const player = await Player.findOne({ token });
if (!player) {
return res.status(401).json({ error: "invalid_token" });
}
res.json({
uid: player.uid,
open_id: player.open_id,
nickname: player.nickname,
level: player.level,
exp: player.exp,
region: player.region,
game_server_id: player.game_server_id,
avatar: "",
title: "",
banned: false
});
});
app.all("/oauth/garena", async (req, res) => {
res.status(200).json({
success: true,
result: "ok"
});
});
app.all("/oauth/login", async (req, res) => {
res.status(200).json({
success: true,
login: true
});
});
//
app.post("/api/heartbeat", (req, res) => {
res.json({
status: "ok",
server_time: Date.now()
});
});
//====
// =====================
// πŸ“ REGISTER
// =====================
/*app.post("/register", async (req, res) => {
const { nickname, device_id, client_version } = req.body;
if (!device_id) {
return res.status(400).json({ error: "device_id_required" });
}
// 1 device = 1 akun
const exist = await Player.findOne({ device_id });
if (exist) {
return res.status(403).json({
error: "device_already_registered",
uid: exist.uid,
token: exist.token
});
}
const uid = generateUID();
const token = generateToken(uid);
const open_id = `guest_${uid}`;
const player = await Player.create({
uid,
open_id,
nickname: nickname || "Guest",
device_id,
token,
game_server_id: 1,
level: 100,
exp: 25000000,
coins: 999999,
gems: 5600,
ranking_points: 1000,
rank: 1,
client_version
});
res.json({
status: "success",
uid: player.uid,
token: player.token
});
});
// =====================
// πŸ” LOGIN
// =====================
app.post("/oauth/login", async (req, res) => {
const rawUid = req.body.uid;
const token = req.body.token || req.body.access_token;
const uid = Number(rawUid);
if (!uid || isNaN(uid) || !token) {
return res.json({
success: false,
error: "invalid_params"
});
}
const player = await Player.findOne({ uid, token });
if (!player) {
return res.json({
success: false,
error: "invalid_auth"
});
}
if (player.banned) {
return res.json({
success: false,
error: "account_banned"
});
}
// πŸ”₯ LOGIN VALID β†’ FB CONNECT SUCCESS
res.status(200).json({
success: true,
redirect_url: "fbconnect://success",
access_token: token,
uid: player.uid,
open_id: player.open_id,
game_server_id: player.game_server_id,
session_key: player.token,
access_token: player.token
});
});
///
app.get("/oauth/user/info/gett", async (req, res) => {
const uid = Number(req.query.uid);
const token =
req.query.access_token ||
req.query.token ||
req.headers["authorization"];
if (!uid || isNaN(uid) || !token) {
return res.status(200).json({
success: false,
error_code: 190,
error_msg: "Invalid params"
});
}
const player = await Player.findOne({ uid, token });
if (!player) {
return res.status(200).json({
success: false,
error_code: 401,
error_msg: "Invalid token"
});
}
return res.status(200).json({
success: true,
error_code: 0,
error_msg: "",
data: {
uid: player.uid,
open_id: player.open_id,
nickname: player.nickname || "Guest",
avatar: "",
level: player.level,
region: "BR",
game_server_id: player.game_server_id
}
});
});
app.get("/api/heartbeat", async (req, res) => {
const uid = Number(req.query.uid);
const token = req.query.token || req.query.session_key;
// ❗ Jangan bikin heartbeat gagal
return res.status(200).json({
success: true,
error_code: 0,
server_time: Math.floor(Date.now() / 1000)
});
});*/
// =====================
// πŸ’Ύ AUTO SAVE (TOKEN PROTECTED)
// =====================
app.post("/save", async (req, res) => {
const { uid, token, ...data } = req.body;
const player = await Player.findOne({ uid, token });
if (!player) return res.status(401).json({ error: "Unauthorized" });
await Player.updateOne({ uid }, { $set: data });
res.json({ status: "saved" });
});
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "public", "register.html"));
});
// REGISTER PAGE
app.get("/v2.5/dialog/oauth", (req, res) => {
res.sendFile(
path.join(__dirname, "public", "login.html")
);
});
// =====================
// 🌐 START SERVER
// =====================
app.use((req, res, next) => {
res.setHeader("Content-Type", "application/json");
next();
});
app.use((req, res) => {
res.status(404).json({
error: "not_found"
});
});
const PORT = 7860;
app.listen(PORT, () => {
console.log("πŸš€ Server running on port", PORT);
});