diff --git a/submissions/Cross-Platform-Wallet-Bot/chimoney/createWallet.js b/submissions/Cross-Platform-Wallet-Bot/chimoney/createWallet.js new file mode 100644 index 00000000..eeb050cb --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/chimoney/createWallet.js @@ -0,0 +1,24 @@ +const axios = require("axios"); +require('dotenv').config({ path: '../.env' }); + + +async function createWallet(user_id) { + const CHIMONEY_BASE_URL = process.env.CHIMONEY_BASE_URL; + + const url = `${CHIMONEY_BASE_URL}/multicurrency-wallets/create`; + const payload = { name: user_id }; + + const walResponse = await axios.post(url, payload, { + headers: { + "Accept": "application/json", + "Content-Type": "application/json", + "X-API-KEY": process.env.API_KEY + } + }); + + return walResponse.data; +} + +module.exports = { + createWallet +}; diff --git a/submissions/Cross-Platform-Wallet-Bot/chimoney/depositFund.js b/submissions/Cross-Platform-Wallet-Bot/chimoney/depositFund.js new file mode 100644 index 00000000..658e8346 --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/chimoney/depositFund.js @@ -0,0 +1,37 @@ +const axios = require("axios"); +const fs = require("fs").promises; +require('dotenv').config({ path: '../.env' }); + + +async function depositFund(accChiUid, amount) { + const CHIMONEY_BASE_URL = process.env.CHIMONEY_BASE_URL; + + const url = `${CHIMONEY_BASE_URL}/multicurrency-wallets/transfer`; + + const payload = { + amountToSend: amount, + originCurrency: "USD", + receiver: accChiUid, + destinationCurrency: "USD" + }; + + + try { + const walResponse = await axios.post(url, payload, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + "X-API-KEY": process.env.API_KEY, + }, + }); + + return; + } catch (error) { + console.error("Error occurred:", error.response ? error.response.data : error.message); + throw error; + } +} + +module.exports = { + depositFund, +}; diff --git a/submissions/Cross-Platform-Wallet-Bot/chimoney/fundWallet.js b/submissions/Cross-Platform-Wallet-Bot/chimoney/fundWallet.js new file mode 100644 index 00000000..59413f3e --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/chimoney/fundWallet.js @@ -0,0 +1,66 @@ +const axios = require("axios"); +const { platform } = require("os"); +const fs = require("fs").promises; +require('dotenv').config({ path: '../.env' }); + + +async function fundWallet(accChiUid, amount, firstName, userId, platform) { + const CHIMONEY_BASE_URL = process.env.CHIMONEY_BASE_URL; + const CHIMONEY_REDIRECT_URL = process.env.CHIMONEY_REDIRECT_URL; + const CHIMONEY_PAYMENT_EMAIL = process.env.CHIMONEY_PAYMENT_EMAIL; + + const url = `${CHIMONEY_BASE_URL}/payment/initiate`; + + const payload = { + valueInUSD: amount, + payerEmail: CHIMONEY_PAYMENT_EMAIL, + redirect_url: CHIMONEY_REDIRECT_URL, + // walletID: accChiUid, + narration: `Deposit of ${amount} by ${firstName}`, + // subAccount: accChiUid, + }; + + + try { + const walResponse = await axios.post(url, payload, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + "X-API-KEY": process.env.API_KEY, + }, + }); + + + const { id, valueInUSD, redeemData, issueID } = walResponse.data.data; + + const transactionData = { + id, + amount: valueInUSD, + userId, + accChiId: accChiUid, + issueID, + platform: platform + }; + + let existingData = []; + try { + const data = await fs.readFile("transaction.json"); + existingData = JSON.parse(data); + } catch (error) { + console.log("No existing transaction data found, starting fresh."); + } + + existingData.push(transactionData); + + await fs.writeFile("transaction.json", JSON.stringify(existingData, null, 2)); + + return walResponse.data; + } catch (error) { + console.error("Error occurred:", error.response ? error.response.data : error.message); + throw error; + } +} + +module.exports = { + fundWallet, +}; diff --git a/submissions/Cross-Platform-Wallet-Bot/chimoney/realName.js b/submissions/Cross-Platform-Wallet-Bot/chimoney/realName.js new file mode 100644 index 00000000..80183fb7 --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/chimoney/realName.js @@ -0,0 +1,30 @@ +const axios = require("axios"); +require('dotenv').config({ path: '../.env' }); + + +async function realName(accChiId, firstName, lastName) { + const CHIMONEY_BASE_URL = process.env.CHIMONEY_BASE_URL; + + const url = `${CHIMONEY_BASE_URL}/multicurrency-wallets/update`; + const payload = { + "meta": { "newKey": "New Value" }, //I don't know what this is, but it's required + "id": accChiId, + "firstName": firstName, + "lastName": lastName + } + console.log(payload) + + const walResponse = await axios.post(url, payload, { + headers: { + "Accept": "application/json", + "Content-Type": "application/json", + "X-API-KEY": process.env.API_KEY + } + }); + console.log(walResponse.data); + return walResponse.data; +} + +module.exports = { + realName +}; diff --git a/submissions/Cross-Platform-Wallet-Bot/chimoney/sendFund.js b/submissions/Cross-Platform-Wallet-Bot/chimoney/sendFund.js new file mode 100644 index 00000000..504ba21f --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/chimoney/sendFund.js @@ -0,0 +1,65 @@ +const axios = require("axios"); +const fs = require("fs").promises; +require('dotenv').config({ path: '../.env' }); + + +async function sendFund(accChiUid, amount, receiverChiUid, platform, recId) { + const CHIMONEY_BASE_URL = process.env.CHIMONEY_BASE_URL; + + const url = `${CHIMONEY_BASE_URL}/multicurrency-wallets/transfer`; + + + const payload = { + "sender": accChiUid, + "amountToSend": amount, + "originCurrency": "USD", + "destinationCurrency": "USD", + "receiver": receiverChiUid + } + + + try { + const walResponse = await axios.post(url, payload, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + "X-API-KEY": process.env.API_KEY, + }, + }); + + + + + const { id, valueInUSD, redeemData, issueID } = walResponse.data.data; + + const transactionData = { + id, + amount: amount, + userId: recId, + accChiId: "", + issueID, + platform: platform + }; + + let existingData = []; + try { + const data = await fs.readFile("transaction.json"); + existingData = JSON.parse(data); + } catch (error) { + console.log("No existing transaction data found, starting fresh."); + } + + existingData.push(transactionData); + + await fs.writeFile("transaction.json", JSON.stringify(existingData, null, 2)); + + return; + } catch (error) { + console.error("Error occurred:", error.response ? error.response.data : error.message); + throw error; + } +} + +module.exports = { + sendFund, +}; diff --git a/submissions/Cross-Platform-Wallet-Bot/chimoney/updateBalance.js b/submissions/Cross-Platform-Wallet-Bot/chimoney/updateBalance.js new file mode 100644 index 00000000..632df637 --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/chimoney/updateBalance.js @@ -0,0 +1,34 @@ +const axios = require("axios"); +const fs = require("fs").promises; +require('dotenv').config({ path: '../.env' }); + +async function updateBalance(accChiUid) { + const CHIMONEY_BASE_URL = process.env.CHIMONEY_BASE_URL; + + const url = `${CHIMONEY_BASE_URL}/multicurrency-wallets/get?id=${accChiUid}`; + + try { + const walResponse = await axios.get(url, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + "X-API-KEY": process.env.API_KEY, + }, + }); + + const jsonData = walResponse.data; + + const chiWallet = jsonData.data.wallets.find(wallet => wallet.type === 'chi'); + const chiBalance = chiWallet.balance; + + + return chiBalance; + } catch (error) { + console.error("Error occurred:", error.response ? error.response.data : error.message); + throw error; + } +} + +module.exports = { + updateBalance, +}; diff --git a/submissions/Cross-Platform-Wallet-Bot/discord.js b/submissions/Cross-Platform-Wallet-Bot/discord.js new file mode 100644 index 00000000..ed3290ac --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/discord.js @@ -0,0 +1,162 @@ +require('dotenv').config(); +const { Client, GatewayIntentBits, Partials, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); +const fs = require('fs'); +const { setUserPendingAction } = require('./saver'); +const { newMessage, getUserData } = require('./main'); +const { chiPayment } = require('./webhook/chiPayment'); + +const client = new Client({ + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.MessageContent, + GatewayIntentBits.DirectMessages + ], + partials: [ + Partials.Channel, + Partials.Message + ] +}); + +client.once('ready', () => { + console.log(`Logged in as ${client.user.tag}!`); +}); + +client.on('messageCreate', async (message) => { + if (message.author.bot) return; + + const user = getUserData(message.author.id); + const msgData = { + chat_id: message.author.id, + msgId: message.id, + msgFromId: message.author.id, + msgFromFirstName: message.author.username || '', + msgType: message.channel.type, + canSendImage: "true", + canSendText: "true", + canSendButton: "true", + platformType: "Discord", + }; + + if (user && user.pendingAction) { + + const data = fs.readFileSync('pendingAction.json', 'utf8'); + const actionList = JSON.parse(data); + const userNameAction = actionList.find(item => item.name === user.pendingAction); + + if (userNameAction) { + const new_type = userNameAction.action; + + const response = await newMessage({ + type: new_type, + ...msgData, + msgText: message.content, + datetime: new Date(), + }); + + if (response && response.message) { + if (response.sendButton) { + sendMsgButton(message.channel, response); + } else { + message.channel.send(response.message); + } + } + } else { + console.log('Action not found.'); + message.channel.send("An error occurred, please try again later."); + } + } else { + + const response = await newMessage({ + type: 'message', + ...msgData, + msgText: message.content, + datetime: new Date(), + }); + + if (response.sendButton) { + sendMsgButton(message.channel, response); + } else if (response.message) { + message.channel.send(response.message); + } + } +}); + +client.on('interactionCreate', async (interaction) => { + if (!interaction.isButton()) return; + + const action = interaction.customId; + const msgData = { + chat_id: interaction.user.id, + msgFromId: interaction.user.id, + msgFromFirstName: interaction.user.username || '', + msgType: interaction.channel.type, + canSendImage: "true", + canSendText: "true", + canSendButton: "true", + platformType: "Discord", + }; + + if (action === 'accept_tos') { + const response = await newMessage({ type: 'accept_toc', ...msgData, datetime: new Date() }); + if (response.message) { + if (response.sendButton) { + sendMsgButton(interaction.channel, response); + } else { + interaction.reply(response.message); + } + } + } else if (action === 'fund_wallet') { + const response = await newMessage({ type: 'fund_wallet', ...msgData, datetime: new Date() }); + if (response.message) { + if (response.sendButton) { + sendMsgButton(interaction.channel, response); + } else { + interaction.reply(response.message); + } + } + } else if (action === 'send_fund') { + const response = await newMessage({ type: 'send_fund', ...msgData, datetime: new Date() }); + if (response.message) { + if (response.sendButton) { + sendMsgButton(interaction.channel, response); + } else { + interaction.reply(response.message); + } + } + } +}); + +function sendMsgButton(channel, response) { + const buttons = response.buttons.map((btn) => { + if (btn.type === 'url') { + return new ButtonBuilder() + .setLabel(btn.caption) + .setURL(btn.body) + .setStyle(ButtonStyle.Link); + } else if (btn.type === 'callback') { + return new ButtonBuilder() + .setLabel(btn.caption) + .setCustomId(btn.action_name) + .setStyle(ButtonStyle.Primary); + } + return null; + }).filter(Boolean); + + const row = new ActionRowBuilder().addComponents(buttons); + + channel.send({ + content: response.title, + components: [row] + }); +} + +async function processWebhook() { + const sendClient = client; + const [userId, msg, platform] = await chiPayment(sendClient); + if (platform === "Discord") { + await sendClient.users.fetch(userId).then(user => user.send(msg)); + } +} +processWebhook(); +client.login(process.env.DISCORD_BOT_TOKEN); diff --git a/submissions/Cross-Platform-Wallet-Bot/main.js b/submissions/Cross-Platform-Wallet-Bot/main.js new file mode 100644 index 00000000..103de320 --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/main.js @@ -0,0 +1,247 @@ +const { isUserNew, saveNewUser, updateUserAcceptance, getUserInfo, deletePendingRecipient, setUserPendingAction, updateUserBalance, getPendingRecipient, getUserDataByAccountId, savePendingRecipient, checkUserAcceptance, updateUserName } = require('./saver'); +require('dotenv').config(); +const { createWallet } = require('./chimoney/createWallet'); +const fs = require("fs"); +const { fundWallet } = require('./chimoney/fundWallet'); +const { updateBalance } = require('./chimoney/updateBalance'); +const { sendFund } = require('./chimoney/sendFund'); + + +const TOC_URL = process.env.TOC_URL; + +const newMessage = async (messageData) => { + const chatId = messageData.chat_id; + + if (messageData.type === 'fund_wallet') { + setUserPendingAction(chatId, 'fund_wallet'); + return { + message: 'Please enter the amount you want to add to your wallet:', + }; + } + + + + if (messageData.type === 'send_fund') { + const user = await getUserData(chatId); + + if (user.balance <= 0) { + return { message: "You don't have sufficient funds in your wallet to send." }; + } + + await setUserPendingAction(chatId, 'send_fund_account'); + + return { + message: "Please enter the recipient's account number to send funds to:", + }; + } + + + + + + if (messageData.type === 'send_fund_account_input') { + const recipientAccountId = messageData.msgText; + + if (!isValidAccountNumber(recipientAccountId)) { + return { message: "Invalid account number. Please enter a 10-digit number." }; + } + + const recipient = await getUserDataByAccountId(recipientAccountId); + + if (!recipient) { + return { message: "No user found with that account ID. Please try again." }; + } + + await savePendingRecipient(chatId, recipient); + + await setUserPendingAction(chatId, 'send_fund_amount'); + return { + message: `Recipient found: ${recipient.first_name} ${recipient.last_name}.\nPlease enter the amount to send:`, + }; + } + + + if (messageData.type === 'send_fund_amount_input') { + const amount = parseFloat(messageData.msgText); + const platform = messageData.platformType; + + + if (isNaN(amount) || amount <= 0) { + return { message: "Please enter a valid amount to send." }; + } + + const user = await getUserData(chatId); + var recipient = await getPendingRecipient(chatId); + var recipient = recipient.recipient; + + if (amount > user.balance) { + return { message: "You don't have enough balance to send this amount." }; + } + + var recaccChiUid = recipient.accChiUid; + await sendFund(accChiUid, amount, recaccChiUid, platform, recipient.chatId); + await updateBalance(chatId); + + await setUserPendingAction(chatId, null); + await deletePendingRecipient(recipient.chat_id); + + return { + message: `Successfully sent $${amount} to ${recipient.first_name} ${recipient.last_name}.`, + }; + } + + + + if (messageData.type === 'fund_wallet_amount') { + const amount = parseFloat(messageData.msgText); + const platform = messageData.platformType; + + if (!/^\d+$/.test(amount) || amount <= 1) { + return { message: 'Please enter a valid amount to fund your wallet.' }; + } + + + var fundingInfo = await getUserInfo(chatId); + + + var accChiId = fundingInfo.accChiId; + var firstName = fundingInfo.first_name; + + setUserPendingAction(chatId, null); + var payInfo = await fundWallet(accChiId, amount, firstName, chatId, platform); + + return { + message: `Click the link below to fund your wallet with $${amount}:\n${payInfo.data.paymentLink}`, + }; + } + + if (messageData.type === 'user_name_input') { + const uName = messageData.msgText; + + + if (!isValidName(uName)) { + setUserPendingAction(chatId, 'user_name'); + return { + message: 'Please enter a valid name:', + }; + } + + + await updateUserName(chatId, uName); + await setUserPendingAction(chatId, null); + const user = getUserData(chatId); + + + return { + sendButton: true, + message: `Welcome ${uName}:`, + title: `${user.first_name} ${user.last_name}\nAccount Number: ${user.accNo}\nCurrent Balance: $${user.balance}`, + buttons: [ + { type: 'callback', body: 'Fund Wallet', caption: "Fund Wallet", action_name: "fund_wallet" }, + { type: 'callback', body: 'Send Funds', caption: "Send Funds", action_name: "send_fund" } + ] + }; + } + + + if (messageData.type === 'accept_toc') { + const userAccepted = checkUserAcceptance(chatId); + if (!userAccepted) { + updateUserAcceptance(chatId, true); + const user = getUserData(chatId); + await setUserPendingAction(chatId, 'user_name'); + return { + message: `Thank you for accepting the Terms of Service.\n\n Enter your real name:` + }; + } else { + const user = getUserData(chatId); + return { + sendButton: true, + message: `You have already accepted the Terms of Service.\n\nYour balance: $${user.balance}\nName: ${user.first_name} ${user.last_name}`, + buttons: [ + { type: 'callback', caption: "Send Money", action_name: "fund_wallet" }, + { type: 'callback', caption: "Send Funds", action_name: "send_fund" } + ] + }; + } + } + + if (isUserNew(chatId)) { + + var accChiId = `user_${chatId}`; + + var userWallet = await createWallet(accChiId); + + var accChiUid = userWallet.data.uid; + var bal = await updateBalance(accChiUid); + var accNo = generateRandom10DigitNumber(); + + saveNewUser({ + chat_id: chatId, + accChiId: accChiId, + accChiUid: accChiUid, + first_name: messageData.msgFromFirstName || '', + last_name: messageData.msgFromLastName || '', + username: messageData.msgFromUsername || '', + platform: messageData.platformType, + created_at: new Date(), + accepted_toc: false, + balance: bal, + chiId: "", + accNo: accNo + }); + + if (messageData.canSendButton) { + + const userAccepted = checkUserAcceptance(chatId); + if (!userAccepted) { + return { + sendButton: true, + title: "Terms of Service", + buttons: [ + { type: 'url', body: TOC_URL, caption: "View Terms of Service", action_name: "view_toc" }, + { type: 'callback', body: 'Accept ToC', caption: "Accept", action_name: "accept_tos" } + ] + }; + } + } + } + + + + const user = getUserData(chatId); + + + return { + sendButton: true, + title: `Account Summary\n\n${user.first_name} ${user.last_name}\nAccount Number: ${user.accNo}\nCurrent Balance: $${user.balance}`, + buttons: [ + { type: 'callback', caption: "Fund Wallet", action_name: "fund_wallet" }, + { type: 'callback', caption: "Send Funds", action_name: "send_fund" } + ] + }; +}; + +const getUserData = (chatId) => { + const users = JSON.parse(fs.readFileSync('users.json', 'utf8')); + return users[chatId] || {}; +}; + +function isValidName(uName) { + const namePattern = /^[A-Za-z]+(?:\s+[A-Za-z]+)+$/; + return namePattern.test(uName); +} + +function generateRandom10DigitNumber() { + return Math.floor(1000000000 + Math.random() * 9000000000).toString(); +} + +function isValidAccountNumber(accountNumber) { + return /^\d{10}$/.test(accountNumber); +} + + +module.exports = { + newMessage, + getUserData +}; diff --git a/submissions/Cross-Platform-Wallet-Bot/package.json b/submissions/Cross-Platform-Wallet-Bot/package.json new file mode 100644 index 00000000..70e4af83 --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/package.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "chimoneyjs": "^1.2.0", + "discord.js": "^14.16.3", + "dotenv": "^16.4.5", + "express": "^4.21.1", + "qrcode-terminal": "^0.12.0", + "telegraf": "^4.16.3", + "whatsapp-web.js": "^1.26.0" + } +} diff --git a/submissions/Cross-Platform-Wallet-Bot/pendingAction.json b/submissions/Cross-Platform-Wallet-Bot/pendingAction.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/pendingAction.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/submissions/Cross-Platform-Wallet-Bot/pendingRecipient.json b/submissions/Cross-Platform-Wallet-Bot/pendingRecipient.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/pendingRecipient.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/submissions/Cross-Platform-Wallet-Bot/saver.js b/submissions/Cross-Platform-Wallet-Bot/saver.js new file mode 100644 index 00000000..9c206476 --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/saver.js @@ -0,0 +1,148 @@ +const fs = require('fs'); +const filePath = './users.json'; +const { realName } = require("./chimoney/realName") +const ensureFileExists = () => { + if (!fs.existsSync(filePath)) { + fs.writeFileSync(filePath, JSON.stringify({}, null, 2)); + } +}; + +const isUserNew = (chatId) => { + ensureFileExists(); + const users = JSON.parse(fs.readFileSync(filePath, 'utf8')); + return !users[chatId]; +}; + +const getUserInfo = (chatId) => { + try { + ensureFileExists(); + const users = JSON.parse(fs.readFileSync(filePath, 'utf8')); + if (users[chatId]) { + const { accChiUid: accChiId, first_name } = users[chatId]; + return { accChiId, first_name }; + } + return {}; + } catch (error) { + console.error('Error accessing user info:', error); + return {}; + } +}; + + +const saveNewUser = (user) => { + ensureFileExists(); + const users = JSON.parse(fs.readFileSync(filePath, 'utf8')); + users[user.chat_id] = user; + var gg = fs.writeFileSync(filePath, JSON.stringify(users, null, 2)); + +}; + +const checkUserAcceptance = (chatId) => { + ensureFileExists(); + const users = JSON.parse(fs.readFileSync(filePath, 'utf8')); + return users[chatId] && users[chatId].accepted_toc; +}; + + +const updateUserAcceptance = (chatId, accepted) => { + ensureFileExists(); + const users = JSON.parse(fs.readFileSync(filePath, 'utf8')); + if (users[chatId]) { + users[chatId].accepted_toc = accepted; + fs.writeFileSync(filePath, JSON.stringify(users, null, 2)); + } +}; + + +const updateUserBalance = (chatId, amount) => { + ensureFileExists(); + const users = JSON.parse(fs.readFileSync(filePath, 'utf8')); + if (users[chatId]) { + users[chatId].balance = amount; + fs.writeFileSync(filePath, JSON.stringify(users, null, 2)); + } +}; + + +const updateUserName = async (chatId, uName) => { + var [firstName, lastName] = splitName(uName); + + + ensureFileExists(); + var users = JSON.parse(fs.readFileSync(filePath, 'utf8')); + if (users[chatId]) { + + var accChiUid = users[chatId].accChiUid; + await realName(accChiUid, firstName, lastName); + + users[chatId].first_name = firstName; + users[chatId].last_name = lastName; + fs.writeFileSync(filePath, JSON.stringify(users, null, 2)); + } +}; + +const setUserPendingAction = (chatId, action) => { + const users = JSON.parse(fs.readFileSync(filePath, 'utf8')); + if (users[chatId]) { + users[chatId].pendingAction = action; + fs.writeFileSync(filePath, JSON.stringify(users, null, 2)); + } +}; + + +function capitalize(word) { + return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); +} + +function splitName(uName) { + const nameParts = uName.trim().split(/\s+/); + if (nameParts.length < 2) { + return null; + } + const firstName = capitalize(nameParts[0]); + const lastName = nameParts.slice(1).map(capitalize).join(" "); + return [firstName, lastName]; +} + +const getUserDataByAccountId = (accountId) => { + const users = JSON.parse(fs.readFileSync('users.json', 'utf8')); + return Object.values(users).find(user => user.accNo === accountId); +}; + +const savePendingRecipient = (chatId, recipient) => { + let data = fs.readFileSync('pendingRecipient.json', 'utf8'); + let pendingRecipients = JSON.parse(data); + pendingRecipients = pendingRecipients.filter(item => item.chatId !== chatId); + + pendingRecipients.push({ + chatId: chatId, + recipient: recipient + }); + + fs.writeFileSync('pendingRecipient.json', JSON.stringify(pendingRecipients, null, 2)); +}; + + +const getPendingRecipient = (chatId) => { + const data = fs.readFileSync('pendingRecipient.json', 'utf8'); + const pendingRecipients = JSON.parse(data); + + const recipient = pendingRecipients.find(item => item.chatId === chatId); + + return recipient || null; +}; + + +const deletePendingRecipient = async (chatId) => { + let data = fs.readFileSync('pendingRecipient.json', 'utf8'); + let pendingRecipients = JSON.parse(data); + + pendingRecipients = pendingRecipients.filter(item => item.chatId !== chatId); + + fs.writeFileSync('pendingRecipient.json', JSON.stringify(pendingRecipients, null, 2)); +}; + + + + +module.exports = { getPendingRecipient, getUserDataByAccountId, isUserNew, savePendingRecipient, deletePendingRecipient, saveNewUser, setUserPendingAction, checkUserAcceptance, updateUserBalance, getUserInfo, updateUserAcceptance, updateUserName }; \ No newline at end of file diff --git a/submissions/Cross-Platform-Wallet-Bot/telegram.js b/submissions/Cross-Platform-Wallet-Bot/telegram.js new file mode 100644 index 00000000..7512bbae --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/telegram.js @@ -0,0 +1,223 @@ +require('dotenv').config(); +const { Telegraf, Markup } = require('telegraf'); +const { setUserPendingAction } = require('./saver'); +const { newMessage, getUserData } = require('./main'); +const { message } = require('telegraf/filters'); +const fs = require('fs'); +const { chiPayment } = require('./webhook/chiPayment'); + +const bot = new Telegraf(process.env.BOT_TOKEN); +console.log("Logged in to telegram bot!") +bot.start((ctx) => ctx.reply('Welcome')); + +bot.on(message('text'), async (ctx) => { + const msg = ctx.message; + const chatId = msg.chat.id; + const user = getUserData(chatId); + + + if (user && user.pendingAction) { + + const data = fs.readFileSync('pendingAction.json', 'utf8'); + + const actionList = JSON.parse(data); + + const userNameAction = actionList.find(item => item.name === user.pendingAction); + + if (userNameAction) { + var new_type = userNameAction.action; + + + const response = await newMessage({ + type: new_type, + chat_id: chatId, + msgText: msg.text, + datetime: new Date(), + msgId: msg.message_id, + msgFromId: msg.from.id, + msgFromFirstName: msg.from.first_name || '', + msgFromLastName: msg.from.last_name || '', + msgFromUsername: msg.from.username || '', + msgType: msg.chat.type, + canSendImage: "true", + canSendText: "true", + canSendButton: "true", + platformType: "Telegram", + }); + + if (response && response.message) { + if (response && response.sendButton) { + sendMsgButton(ctx, response); + } + + else if (response && response.message) { + ctx.reply(response.message); + } + } + + } else { + console.log('Action not found.'); + ctx.reply("An error occured pls try again later"); + + } + + } + else { + + const messageData = { + body: msg.text, + type: 'message', + datetime: new Date(), + chat_id: msg.chat.id, + msgId: msg.message_id, + msgFromId: msg.from.id, + msgFromFirstName: msg.from.first_name || '', + msgFromLastName: msg.from.last_name || '', + msgFromUsername: msg.from.username || '', + msgType: msg.chat.type, + msgText: msg.text, + canSendImage: "true", + canSendText: "true", + canSendButton: "true", + platformType: "Telegram", + }; + + + const response = await newMessage(messageData); + + if (response && response.sendButton) { + sendMsgButton(ctx, response); + } + + else if (response && response.message) { + ctx.reply(response.message); + } + + } +}); + + + + + + + +bot.action('accept_tos', async (ctx) => { + + const messageData = { + type: 'accept_toc', + chat_id: ctx.chat.id, + datetime: new Date(), + msgId: msg.message_id, + msgFromId: msg.from.id, + msgFromFirstName: msg.from.first_name || '', + msgFromLastName: msg.from.last_name || '', + msgFromUsername: msg.from.username || '', + msgType: msg.chat.type, + canSendImage: "true", + canSendText: "true", + canSendButton: "true", + platformType: "Telegram", + }; + + const response = await newMessage(messageData); + + if (response && response.message) { + if (response && response.sendButton) { + sendMsgButton(ctx, response); + } + + else if (response && response.message) { + ctx.reply(response.message); + } + } + +}); + +bot.action('fund_wallet', async (ctx) => { + const messageData = { + type: 'fund_wallet', + chat_id: ctx.chat.id, + datetime: new Date(), + msgId: msg.message_id, + msgFromId: msg.from.id, + msgFromFirstName: msg.from.first_name || '', + msgFromLastName: msg.from.last_name || '', + msgFromUsername: msg.from.username || '', + msgType: msg.chat.type, + canSendImage: "true", + canSendText: "true", + canSendButton: "true", + platformType: "Telegram", + }; + + const response = await newMessage(messageData); + if (response && response.message) { + if (response && response.sendButton) { + sendMsgButton(ctx, response); + } + + else if (response && response.message) { + ctx.reply(response.message); + } + } +}); + + +bot.action('send_fund', async (ctx) => { + const messageData = { + type: 'send_fund', + chat_id: ctx.chat.id, + datetime: new Date(), + msgId: msg.message_id, + msgFromId: msg.from.id, + msgFromFirstName: msg.from.first_name || '', + msgFromLastName: msg.from.last_name || '', + msgFromUsername: msg.from.username || '', + msgType: msg.chat.type, + canSendImage: "true", + canSendText: "true", + canSendButton: "true", + platformType: "Telegram", + }; + + const response = await newMessage(messageData); + if (response && response.message) { + if (response && response.sendButton) { + sendMsgButton(ctx, response); + } + + else if (response && response.message) { + ctx.reply(response.message); + } + } +}); + + +function sendMsgButton(ctx, response) { + const buttons = response.buttons.map((btn) => { + if (btn.type === 'url') { + return Markup.button.url(btn.caption, btn.body); + } else if (btn.type === 'callback') { + return Markup.button.callback(btn.caption, btn.action_name); + } + return []; + }); + + ctx.reply( + response.title, + Markup.inlineKeyboard(buttons) + ); +} + + +async function processWebhook() { + var sendClient = bot.telegram; + const [userId, msg, platform] = await chiPayment(sendClient); + if (platform === "Telegram") { + await sendClient.sendMessage(userId, msg); + } +} + +processWebhook() +bot.launch(); diff --git a/submissions/Cross-Platform-Wallet-Bot/transaction.json b/submissions/Cross-Platform-Wallet-Bot/transaction.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/transaction.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/submissions/Cross-Platform-Wallet-Bot/users.json b/submissions/Cross-Platform-Wallet-Bot/users.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/users.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/submissions/Cross-Platform-Wallet-Bot/webhook/chiPayment.js b/submissions/Cross-Platform-Wallet-Bot/webhook/chiPayment.js new file mode 100644 index 00000000..4a272fa6 --- /dev/null +++ b/submissions/Cross-Platform-Wallet-Bot/webhook/chiPayment.js @@ -0,0 +1,81 @@ +const express = require('express'); +const fs = require("fs"); +const { depositFund } = require('../chimoney/depositFund'); +const { updateUserBalance } = require('../saver'); +const { updateBalance } = require('../chimoney/updateBalance'); +const app = express(); +const PORT = 3000; + +app.use(express.json()); + +async function chiPayment() { + + app.post('/paymentCompleted', async (req, res) => { + console.log('Received webhook:', req.body); + res.status(200).send('Webhook received'); + + var hookRes = req.body; + + if (hookRes.eventType === "chimoney.payment.completed" || hookRes.eventType === "charge.card.completed") { + var issueID = hookRes.issueID; + const data = fs.readFileSync('transaction.json', 'utf8'); + const transactions = JSON.parse(data); + + const transaction = transactions.find(tx => tx.issueID === issueID); + + if (transaction) { + var amount = transaction.amount; + var accChiUid = transaction.accChiId; + var userId = transaction.userId; + var platform = transaction.platform; + + await depositFund(accChiUid, amount); + + + var msg = `$${amount} have been deposited to your account`; + var bal = await updateBalance(accChiUid); + return [userId, msg, platform]; + + } else { + console.log("No transaction found with this issueID"); + } + } + else if (hookRes.eventType === "payout.wallet.completed") { + var issueID = hookRes.issueID; + const data = fs.readFileSync('transaction.json', 'utf8'); + const transactions = JSON.parse(data); + + const transaction = transactions.find(tx => tx.issueID === issueID); + + if (transaction) { + var amount = transaction.amount; + var accChiUid = transaction.accChiId; + var userId = transaction.userId; + var platform = transaction.platform; + + await depositFund(accChiUid, amount); + + + var msg = `$${amount} have been credit to your account`; + var bal = await updateBalance(accChiUid); + + return [userId, msg, platform]; + + } else { + console.log("No transaction found with this issueID"); + } + } + + + }); + + app.listen(PORT, () => { + console.log(`Webhook server running on http://localhost:${PORT}`); + }); + +} + + +module.exports = { + chiPayment, +};