actions / actions/starter-workflows

Hello

Open
#3,278 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
12.1k
Forks
7.3k
PR merge metrics
No merged PRs in 30d

Description

const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const axios = require('axios');
const crypto = require('crypto');
const app = express();
const server = http.createServer(app);
const io = socketIo(server, { cors: { origin: "*" } });

app.use(express.json());
app.use(express.static('public')); // index.html, withdraw.html is folder mein daal dena

// ==================== DATABASE ====================
// Real app mein MongoDB use karna. Ye demo ke liye hai
let users = {
"user1": { balance: 1000, kyc: true, kycName: "Test User", state: "Maharashtra" }
};
let bankDetails = {}; // { userId: { accNo, ifsc, name, verified: false } }
let pennyDropRequests = {};
let activeRounds = {};
let playerPrices = {
"Virat Kohli": 45, "Bumrah": 40, "Hardik": 38,
"Rohit": 42, "Rashid": 41, "KL Rahul": 39
};
const BLOCKED_STATES = ["Telangana", "Andhra Pradesh", "Assam", "Sikkim", "Nagaland", "Odisha"];

// ==================== MIDDLEWARE ====================
function checkGeoBlock(req, res, next) {
const userId = req.body.userId || req.params.userId;
if (users[userId] && BLOCKED_STATES.includes(users[userId].state)) {
return res.status(403).json({ error: "Tere state mein ye game allow nahi hai" });
}
next();
}

// ==================== WALLET APIs ====================
app.post('/deposit', checkGeoBlock, (req, res) => {
const { userId, amount } = req.body;
// Real mein: Razorpay webhook verify karna yahan
if (!users[userId]) return res.status(400).json({ error: "User nahi mila" });
users[userId].balance += amount;
res.json({ status: "success", newBalance: users[userId].balance });
});

app.post('/save-bank', checkGeoBlock, (req, res) => {
const { userId, accNo, ifsc, name } = req.body;
if (!userId ||!accNo ||!ifsc ||!name) {
return res.status(400).json({ error: "Sab fields bharo" });
}
if (accNo.length < 9 || accNo.length > 18) {
return res.status(400).json({ error: "Account number 9-18 digit ka hona chahiye" });
}
if (!/^[A-Z]{4}0[A-Z0-9]{6}$/.test(ifsc)) {
return res.status(400).json({ error: "IFSC code galat format" });
}
bankDetails[userId] = { accNo, ifsc, name, verified: false };
res.json({ status: "Bank details save ho gaye", data: bankDetails[userId] });
});

app.get('/get-bank/:userId', (req, res) => {
const { userId } = req.params;
res.json({ data: bankDetails[userId] || null });
});

app.post('/initiate-penny-drop', checkGeoBlock, async (req, res) => {
const { userId } = req.body;
if (!bankDetails[userId]) return res.status(400).json({ error: "Pehle bank details save karo" });
if (!users[userId].kyc) return res.status(400).json({ error: "KYC complete karo pehle" });

const { accNo, ifsc, name } = bankDetails[userId];
const utr = 'UTR' + crypto.randomBytes(6).toString('hex').toUpperCase();

// === RAZORPAYX API YAHAN LAGEGA ===
// Demo ke liye maan lete hain success
const nameFromBank = name; // Real mein webhook se aayega

pennyDropRequests[userId] = { utr, nameFromBank, status: "success", amount: 1 };
bankDetails[userId].verified = false;

res.json({ status: "₹1 bhej diya. 2 min mein verify ho jaayega", utr: utr });

});

app.post('/verify-penny-drop', checkGeoBlock, (req, res) => {
const { userId } = req.body;
const request = pennyDropRequests[userId];
const userKycName = users[userId].kycName;

if (!request) return res.status(400).json({ error: "Pehle ₹1 wala request karo" });

if (request.status === "success") {
    const bankName = request.nameFromBank.toLowerCase().replace(/\s/g, '');
    const kycName = userKycName.toLowerCase().replace(/\s/g, '');

    if (bankName === kycName) {
        bankDetails[userId].verified = true;
        delete pennyDropRequests[userId];
        return res.json({ status: "Verified ✅", msg: "Bank account verify ho gaya. Ab withdraw kar sakte ho" });
    } else {
        bankDetails[userId].verified = false;
        return res.status(400).json({
            status: "Failed ❌",
            msg: `Naam match nahi hua. Bank: ${request.nameFromBank}, KYC: ${userKycName}`
        });
    }
} else {
    res.json({ status: "Pending", msg: "Abhi bank se response nahi aaya. 2 min baad try karo" });
}

});

app.post('/withdraw', checkGeoBlock, (req, res) => {
const { userId, amount } = req.body;
if (!users[userId]) return res.status(400).json({ error: "User nahi mila" });
if (!bankDetails[userId]?.verified) return res.status(400).json({ error: "Bank verify karo pehle" });
if (amount < 100) return res.status(400).json({ error: "Minimum ₹100 withdraw" });
if (users[userId].balance < amount) return res.status(400).json({ error: "Balance kam hai" });
if (!users[userId].kyc) return res.status(400).json({ error: "KYC complete karo pehle" });

let tds = amount > 10000? Math.round(amount * 0.30) : 0;
let finalAmount = amount - tds;
users[userId].balance -= amount;

console.log(`PAYOUT: ₹${finalAmount} to ${bankDetails[userId].name}`);
console.log(`A/C: ${bankDetails[userId].accNo}, IFSC: ${bankDetails[userId].ifsc}, TDS: ₹${tds}`);

res.json({ status: "Withdraw request lag gayi", amount: finalAmount, tds: tds, newBalance: users[userId].balance });

});

// ==================== GAME LOGIC ====================
function startNewRound() {
const roundId = Date.now();
activeRounds[roundId] = { startTime: Date.now(), players: {}, status: "betting" };

setTimeout(() => {
    if (activeRounds[roundId]) {
        activeRounds[roundId].status = "live";
        io.emit('round_live', { roundId });
    }
}, 30000);

setTimeout(() => calculateResults(roundId), 180000);
io.emit('new_round', { roundId, playerPrices, timeLeft: 180 });

}

async function calculateResults(roundId) {
const round = activeRounds[roundId];
if (!round) return;
round.status = "ended";

// Real mein: const liveData = await axios.get('https://api.cricapi.com/v1/currentMatches...')
const liveData = {
    "Virat Kohli": { runs: Math.floor(Math.random() * 30) },
    "Bumrah": { wkts: Math.floor(Math.random() * 3) },
    "Hardik": { runs: Math.floor(Math.random() * 25) },
    "Rohit": { runs: Math.floor(Math.random() * 25) },
    "Rashid": { wkts: Math.floor(Math.random() * 3) },
    "KL Rahul": { runs: Math.floor(Math.random() * 20) }
};

let winners = [], maxPoints = -1;
for (let userId in round.players) {
    let totalPoints = 0;
    round.players[userId].team.forEach(p => {
        if (liveData[p]?.runs) totalPoints += liveData[p].runs * 1;
        if (liveData[p]?.wkts) totalPoints += liveData[p].wkts * 20;
    });
    round.players[userId].points = totalPoints;
    if (totalPoints > maxPoints) { maxPoints = totalPoints; winners = [userId]; }
    else if (totalPoints === maxPoints) { winners.push(userId); }
}

winners.forEach(uid => { if (users[uid]) users[uid].balance += 18; });
io.emit('round_result', { roundId, leaderboard: round.players, winners, liveData });
delete activeRounds[roundId];
startNewRound();

}

io.on('connection', (socket) => {
socket.on('join_round', ({ userId, roundId, team }) => {
if (!users[userId]) return socket.emit('error', 'User nahi mila');
if (BLOCKED_STATES.includes(users[userId].state)) return socket.emit('error', 'Tere state mein ban hai');
if (users[userId].balance < 10) return socket.emit('error', 'Balance kam hai');
if (!users[userId].kyc) return socket.emit('error', 'KYC pending');
if (!activeRounds[roundId] || activeRounds[roundId].status!== 'betting') {
return socket.emit('error', 'Betting band ho gayi');
}

    users[userId].balance -= 10;
    activeRounds[roundId].players[userId] = { team, points: 0 };
    socket.emit('joined_success', { newBalance: users[userId].balance });
});

});

// ==================== START SERVER ====================
setInterval(startNewRound, 180000);
startNewRound();
server.listen(3000, () => console.log('Server 3000 pe chal raha. Game on!'));

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue contains a standalone Express server ending at server.listen(3000), but names no repository file, test, requested change, or acceptance criteria. Clarify the intended contribution and how this code should integrate with starter-workflows before identifying an entry point and defining what completion means.

Written by the indexing model from the issue text.

Assessment

Tech stack
express, javascript, mongodb, node.js
Domain
api, backend, database, payments
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
5/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.