[feat] Added telegram functionality

This commit is contained in:
WovenCoast 2024-02-11 11:50:23 +05:00
parent 2a9362ed38
commit 8fe151d593
Signed by: flamexode
GPG Key ID: BB7D370708288E23
8 changed files with 426 additions and 216 deletions

View File

@ -1,6 +1,19 @@
REGISTRATION_OPEN=true
BRANDING_TITLE=
BRANDING_LOGO=
REGISTRATION_OPEN=true # Set to anything except "true" to disable registration
# Telegram
TG_BOTAPI=https://api.telegram.org/bot
TELEGRAM_BOT_TOKEN= # Your Telegram Bot Token
TELEGRAM_CHAT_ID= # Your Telegram Chat ID
# Webpage Settings
BRANDING_TITLE= # Website Title
BRANDING_LOGO= # Website Logo
# Payment Details
BANK_NAME=
ACCOUNT_NAME=
ACCOUNT_NUMBER=
ACCOUNT_NUMBER=
PRICE=
ROAMING_PRICE=
PRICE_CURRENCY=

23
package-lock.json generated
View File

@ -13,10 +13,10 @@
"dotenv": "^16.4.1",
"ejs": "^3.1.9",
"express": "^4.18.2",
"form-data": "^4.0.0",
"multer": "^1.4.5-lts.1"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.7",
"daisyui": "^4.6.2",
"tailwindcss": "^3.4.1"
}
@ -143,18 +143,6 @@
"node": ">=14"
}
},
"node_modules/@tailwindcss/forms": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz",
"integrity": "sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==",
"dev": true,
"dependencies": {
"mini-svg-data-uri": "^1.2.3"
},
"peerDependencies": {
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1"
}
},
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@ -1312,15 +1300,6 @@
"node": ">= 0.6"
}
},
"node_modules/mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
"dev": true,
"bin": {
"mini-svg-data-uri": "cli.js"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",

View File

@ -16,6 +16,7 @@
"dotenv": "^16.4.1",
"ejs": "^3.1.9",
"express": "^4.18.2",
"form-data": "^4.0.0",
"multer": "^1.4.5-lts.1"
},
"devDependencies": {

View File

@ -2,6 +2,8 @@ require("dotenv").config()
let registrationOpen, branding;
const { sendInfo } = require("./src/telegram")
function loadEnv() {
registrationOpen = process.env.REGISTRATION_OPEN === "true"
branding = {
@ -12,6 +14,11 @@ function loadEnv() {
accountNumber: process.env.ACCOUNT_NUMBER || "1234567890",
accountName: process.env.ACCOUNT_NAME || "Account Name",
},
price: {
normal: process.env.PRICE || "100",
roaming: process.env.ROAMING_PRICE || "200",
currency: process.env.PRICE_CURRENCY || "MVR",
}
}
}
loadEnv()
@ -37,31 +44,46 @@ app.use(express.urlencoded({ extended: true }))
// add multer
const multer = require("multer")
fs.mkdirSync("uploads", { recursive: true })
const upload = multer({
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "./uploads")
},
filename: (req, file, cb) => {
cb(null, `${Date.now()}-${file.originalname}`)
}
cb(null, `${Date.now()}- ${req.body["device_name"]} - ${file.originalname}`)
},
})
})
// app.use(upload.single("receipt"))
// routes
app.get("/", (req, res) => {
res.render(registrationOpen ? "index" : "closed", { branding })
res.render(registrationOpen ? "index" : "closed", { branding, message: "" })
});
app.post("/register", upload.single("receipt"), (req, res) => {
app.post("/register", upload.single("transfer_receipt"), (req, res) => {
if (!registrationOpen) {
res.render("closed")
return
return;
}
console.log(req.body)
console.log(req.file)
res.render("success", { branding })
const { customer_name, mac_address, device_name, is_roaming } = req.body
const receipt = req.file;
if (!customer_name || !mac_address || !device_name || !receipt || !is_roaming) {
res.render("index", { branding, message: "Please fill all fields" })
return;
}
sendInfo(receipt.path, customer_name, mac_address, device_name, is_roaming)
.then(() => {
res.render("success", { branding })
})
.catch((error) => {
console.error(error)
res.render("index", { branding, message: "An internal error occurred" })
})
})
const port = process.env.PORT || 4818;

View File

@ -897,13 +897,6 @@ html {
flex-grow: 1;
}
.card-actions {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
gap: 0.5rem;
}
.card figure {
display: flex;
align-items: center;
@ -1078,6 +1071,15 @@ html {
}
}
.btn-outline:hover {
--tw-border-opacity: 1;
border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));
--tw-bg-opacity: 1;
background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
--tw-text-opacity: 1;
color: var(--fallback-b1,oklch(var(--b1)/var(--tw-text-opacity)));
}
.btn-outline.btn-primary:hover {
--tw-text-opacity: 1;
color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));
@ -1090,6 +1092,42 @@ html {
}
}
.btn-outline.btn-secondary:hover {
--tw-text-opacity: 1;
color: var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)));
}
@supports (color: color-mix(in oklab, black, black)) {
.btn-outline.btn-secondary:hover {
background-color: color-mix(in oklab, var(--fallback-s,oklch(var(--s)/1)) 90%, black);
border-color: color-mix(in oklab, var(--fallback-s,oklch(var(--s)/1)) 90%, black);
}
}
.btn-outline.btn-accent:hover {
--tw-text-opacity: 1;
color: var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)));
}
@supports (color: color-mix(in oklab, black, black)) {
.btn-outline.btn-accent:hover {
background-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black);
border-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black);
}
}
.btn-outline.btn-success:hover {
--tw-text-opacity: 1;
color: var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)));
}
@supports (color: color-mix(in oklab, black, black)) {
.btn-outline.btn-success:hover {
background-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black);
border-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black);
}
}
.btn-outline.btn-info:hover {
--tw-text-opacity: 1;
color: var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)));
@ -1102,6 +1140,30 @@ html {
}
}
.btn-outline.btn-warning:hover {
--tw-text-opacity: 1;
color: var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)));
}
@supports (color: color-mix(in oklab, black, black)) {
.btn-outline.btn-warning:hover {
background-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black);
border-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black);
}
}
.btn-outline.btn-error:hover {
--tw-text-opacity: 1;
color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)));
}
@supports (color: color-mix(in oklab, black, black)) {
.btn-outline.btn-error:hover {
background-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black);
border-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black);
}
}
.btn-disabled:hover,
.btn[disabled]:hover,
.btn:disabled:hover {
@ -1271,55 +1333,6 @@ html {
align-items: center;
}
.radio {
flex-shrink: 0;
--chkbg: var(--bc);
height: 1.5rem;
width: 1.5rem;
cursor: pointer;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border-radius: 9999px;
border-width: 1px;
border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));
--tw-border-opacity: 0.2;
}
.select {
display: inline-flex;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
height: 3rem;
min-height: 3rem;
padding-left: 1rem;
padding-right: 2.5rem;
font-size: 0.875rem;
line-height: 1.25rem;
line-height: 2;
border-radius: var(--rounded-btn, 0.5rem);
border-width: 1px;
border-color: transparent;
--tw-bg-opacity: 1;
background-color: var(--fallback-b1,oklch(var(--b1)/var(--tw-bg-opacity)));
background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
linear-gradient(135deg, currentColor 50%, transparent 50%);
background-position: calc(100% - 20px) calc(1px + 50%),
calc(100% - 16.1px) calc(1px + 50%);
background-size: 4px 4px,
4px 4px;
background-repeat: no-repeat;
}
.select[multiple] {
height: auto;
}
.steps {
display: inline-grid;
grid-auto-flow: column;
@ -1340,6 +1353,14 @@ html {
min-width: 4rem;
}
.alert-error {
border-color: var(--fallback-er,oklch(var(--er)/0.2));
--tw-text-opacity: 1;
color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)));
--alert-bg: var(--fallback-er,oklch(var(--er)/1));
--alert-bg-mix: var(--fallback-b1,oklch(var(--b1)/1));
}
.btm-nav > *.disabled,
.btm-nav > *[disabled] {
pointer-events: none;
@ -1397,13 +1418,13 @@ html {
border-color: var(--btn-color, var(--fallback-b2));
}
.btn-primary {
--btn-color: var(--fallback-p);
}
.btn-info {
--btn-color: var(--fallback-in);
}
.btn-error {
--btn-color: var(--fallback-er);
}
}
@supports (color: color-mix(in oklab, black, black)) {
@ -1412,10 +1433,35 @@ html {
border-color: color-mix(in oklab, var(--fallback-p,oklch(var(--p)/1)) 90%, black);
}
.btn-outline.btn-secondary.btn-active {
background-color: color-mix(in oklab, var(--fallback-s,oklch(var(--s)/1)) 90%, black);
border-color: color-mix(in oklab, var(--fallback-s,oklch(var(--s)/1)) 90%, black);
}
.btn-outline.btn-accent.btn-active {
background-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black);
border-color: color-mix(in oklab, var(--fallback-a,oklch(var(--a)/1)) 90%, black);
}
.btn-outline.btn-success.btn-active {
background-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black);
border-color: color-mix(in oklab, var(--fallback-su,oklch(var(--su)/1)) 90%, black);
}
.btn-outline.btn-info.btn-active {
background-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black);
border-color: color-mix(in oklab, var(--fallback-in,oklch(var(--in)/1)) 90%, black);
}
.btn-outline.btn-warning.btn-active {
background-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black);
border-color: color-mix(in oklab, var(--fallback-wa,oklch(var(--wa)/1)) 90%, black);
}
.btn-outline.btn-error.btn-active {
background-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black);
border-color: color-mix(in oklab, var(--fallback-er,oklch(var(--er)/1)) 90%, black);
}
}
.btn:focus-visible {
@ -1424,20 +1470,14 @@ html {
outline-offset: 2px;
}
.btn-primary {
--tw-text-opacity: 1;
color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));
outline-color: var(--fallback-p,oklch(var(--p)/1));
}
@supports (color: oklch(0 0 0)) {
.btn-primary {
--btn-color: var(--p);
}
.btn-info {
--btn-color: var(--in);
}
.btn-error {
--btn-color: var(--er);
}
}
.btn-info {
@ -1446,6 +1486,12 @@ html {
outline-color: var(--fallback-in,oklch(var(--in)/1));
}
.btn-error {
--tw-text-opacity: 1;
color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)));
outline-color: var(--fallback-er,oklch(var(--er)/1));
}
.btn.glass {
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
@ -1474,6 +1520,25 @@ html {
background-color: var(--fallback-bc,oklch(var(--bc)/0.2));
}
.btn-outline {
border-color: currentColor;
background-color: transparent;
--tw-text-opacity: 1;
color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
.btn-outline.btn-active {
--tw-border-opacity: 1;
border-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-border-opacity)));
--tw-bg-opacity: 1;
background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
--tw-text-opacity: 1;
color: var(--fallback-b1,oklch(var(--b1)/var(--tw-text-opacity)));
}
.btn-outline.btn-primary {
--tw-text-opacity: 1;
color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)));
@ -1484,6 +1549,36 @@ html {
color: var(--fallback-pc,oklch(var(--pc)/var(--tw-text-opacity)));
}
.btn-outline.btn-secondary {
--tw-text-opacity: 1;
color: var(--fallback-s,oklch(var(--s)/var(--tw-text-opacity)));
}
.btn-outline.btn-secondary.btn-active {
--tw-text-opacity: 1;
color: var(--fallback-sc,oklch(var(--sc)/var(--tw-text-opacity)));
}
.btn-outline.btn-accent {
--tw-text-opacity: 1;
color: var(--fallback-a,oklch(var(--a)/var(--tw-text-opacity)));
}
.btn-outline.btn-accent.btn-active {
--tw-text-opacity: 1;
color: var(--fallback-ac,oklch(var(--ac)/var(--tw-text-opacity)));
}
.btn-outline.btn-success {
--tw-text-opacity: 1;
color: var(--fallback-su,oklch(var(--su)/var(--tw-text-opacity)));
}
.btn-outline.btn-success.btn-active {
--tw-text-opacity: 1;
color: var(--fallback-suc,oklch(var(--suc)/var(--tw-text-opacity)));
}
.btn-outline.btn-info {
--tw-text-opacity: 1;
color: var(--fallback-in,oklch(var(--in)/var(--tw-text-opacity)));
@ -1494,6 +1589,26 @@ html {
color: var(--fallback-inc,oklch(var(--inc)/var(--tw-text-opacity)));
}
.btn-outline.btn-warning {
--tw-text-opacity: 1;
color: var(--fallback-wa,oklch(var(--wa)/var(--tw-text-opacity)));
}
.btn-outline.btn-warning.btn-active {
--tw-text-opacity: 1;
color: var(--fallback-wac,oklch(var(--wac)/var(--tw-text-opacity)));
}
.btn-outline.btn-error {
--tw-text-opacity: 1;
color: var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity)));
}
.btn-outline.btn-error.btn-active {
--tw-text-opacity: 1;
color: var(--fallback-erc,oklch(var(--erc)/var(--tw-text-opacity)));
}
.btn.btn-disabled,
.btn[disabled],
.btn:disabled {
@ -1896,6 +2011,12 @@ details.collapse summary::-webkit-details-marker {
outline-offset: 2px;
}
.mockup-phone .display {
overflow: hidden;
border-radius: 40px;
margin-top: -25px;
}
.mockup-browser .mockup-browser-toolbar .input {
position: relative;
margin-left: auto;
@ -1954,32 +2075,6 @@ details.collapse summary::-webkit-details-marker {
}
}
.radio:focus {
box-shadow: none;
}
.radio:focus-visible {
outline-style: solid;
outline-width: 2px;
outline-offset: 2px;
outline-color: var(--fallback-bc,oklch(var(--bc)/1));
}
.radio:checked,
.radio[aria-checked="true"] {
--tw-bg-opacity: 1;
background-color: var(--fallback-bc,oklch(var(--bc)/var(--tw-bg-opacity)));
background-image: none;
animation: radiomark var(--animation-input, 0.2s) ease-out;
box-shadow: 0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset,
0 0 0 4px var(--fallback-b1,oklch(var(--b1)/1)) inset;
}
.radio:disabled {
cursor: not-allowed;
opacity: 0.2;
}
@keyframes radiomark {
0% {
box-shadow: 0 0 0 12px var(--fallback-b1,oklch(var(--b1)/1)) inset,
@ -2011,51 +2106,6 @@ details.collapse summary::-webkit-details-marker {
}
}
.select:focus {
box-shadow: none;
border-color: var(--fallback-bc,oklch(var(--bc)/0.2));
outline-style: solid;
outline-width: 2px;
outline-offset: 2px;
outline-color: var(--fallback-bc,oklch(var(--bc)/0.2));
}
.select-disabled,
.select:disabled,
.select[disabled] {
cursor: not-allowed;
--tw-border-opacity: 1;
border-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-border-opacity)));
--tw-bg-opacity: 1;
background-color: var(--fallback-b2,oklch(var(--b2)/var(--tw-bg-opacity)));
color: var(--fallback-bc,oklch(var(--bc)/var(--tw-text-opacity)));
--tw-text-opacity: 0.2;
}
.select-disabled::-moz-placeholder, .select:disabled::-moz-placeholder, .select[disabled]::-moz-placeholder {
color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));
--tw-placeholder-opacity: 0.2;
}
.select-disabled::placeholder,
.select:disabled::placeholder,
.select[disabled]::placeholder {
color: var(--fallback-bc,oklch(var(--bc)/var(--tw-placeholder-opacity)));
--tw-placeholder-opacity: 0.2;
}
.select-multiple,
.select[multiple],
.select[size].select:not([size="1"]) {
background-image: none;
padding-right: 1rem;
}
[dir="rtl"] .select {
background-position: calc(0% + 12px) calc(1px + 50%),
calc(0% + 16px) calc(1px + 50%);
}
@keyframes skeleton {
from {
background-position: 150%;
@ -2284,22 +2334,23 @@ details.collapse summary::-webkit-details-marker {
visibility: collapse;
}
.mt-4 {
margin-top: 1rem;
.mx-auto {
margin-left: auto;
margin-right: auto;
}
.mt-8 {
margin-top: 2rem;
}
.block {
display: block;
}
.flex {
display: flex;
}
.h-6 {
height: 1.5rem;
}
.h-\[100vh\] {
height: 100vh;
}
@ -2308,6 +2359,10 @@ details.collapse summary::-webkit-details-marker {
width: 2.5rem;
}
.w-6 {
width: 1.5rem;
}
.w-96 {
width: 24rem;
}
@ -2320,34 +2375,18 @@ details.collapse summary::-webkit-details-marker {
width: 80vw;
}
.w-full {
width: 100%;
}
.max-w-xs {
max-width: 20rem;
}
.flex-1 {
flex: 1 1 0%;
.shrink-0 {
flex-shrink: 0;
}
.items-center {
align-items: center;
}
.justify-end {
justify-content: flex-end;
}
.justify-center {
justify-content: center;
}
.overflow-visible {
overflow: visible;
}
.overflow-x-auto {
overflow-x: auto;
}
@ -2376,8 +2415,8 @@ details.collapse summary::-webkit-details-marker {
background-color: var(--fallback-p,oklch(var(--p)/var(--tw-bg-opacity)));
}
.text-center {
text-align: center;
.stroke-current {
stroke: currentColor;
}
.text-3xl {

30
src/telegram.js Normal file
View File

@ -0,0 +1,30 @@
const fs = require("fs")
const FormData = require('form-data');
const axios = require('axios').default;
async function sendInfo(filepath, customer_name, mac_address, device_name, roaming) {
const caption = `Customer Name: \`${customer_name}\`\nMAC Address: \`${mac_address}\`\nDevice Name: \`${device_name}\`\nRoaming: **${roaming ? "Yes" : "No"}**`
var formData = new FormData();
formData.append("photo", fs.createReadStream(filepath));
const query = new URLSearchParams();
query.append("chat_id", process.env.TELEGRAM_CHAT_ID);
query.append("caption", caption);
query.append("parse_mode", "MarkdownV2");
// upload file to telegram using axios
const response = await axios.post(`${process.env.TG_BOTAPI}${process.env.TELEGRAM_BOT_TOKEN}/sendPhoto?${query.toString()}`, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
if (response.status !== 200) {
console.log(response.data)
}
}
module.exports = {
sendInfo
}

View File

@ -9,6 +9,48 @@
<script>
const blacklistedChars = /\s/g;
function recoverForm() {
const customerName = document.getElementById("customer_name");
const macAddress = document.getElementById("mac_address");
const deviceName = document.getElementById("device_name");
customerName.value = localStorage.getItem("customer_name") || "";
macAddress.value = localStorage.getItem("mac_address") || "";
deviceName.value = localStorage.getItem("device_name") || "";
}
function saveForm() {
const customerName = document.getElementById("customer_name");
const macAddress = document.getElementById("mac_address");
const deviceName = document.getElementById("device_name");
localStorage.setItem("customer_name", customerName.value);
localStorage.setItem("mac_address", macAddress.value);
localStorage.setItem("device_name", deviceName.value);
}
function clearForm() {
localStorage.removeItem("customer_name");
localStorage.removeItem("mac_address");
localStorage.removeItem("device_name");
document.getElementById("customer_name").value = "";
document.getElementById("mac_address").value = "";
document.getElementById("device_name").value = "";
}
function setRoaming() {
const normalPrice = <%- branding.price.normal %>;
const roamingPrice = <%- branding.price.roaming %>;
const currency = "<%- branding.price.currency %>";
const isRoaming = document.getElementById("is_roaming");
const amount = document.getElementById("amount");
if (isRoaming.checked) {
amount.textContent = `Amount: ${roamingPrice} ${currency}`;
} else {
amount.textContent = `Amount: ${normalPrice} ${currency}`;
}
}
function fillDeviceName() {
let deviceType = "";
const macAddress = document.getElementById("mac_address").value;
@ -88,6 +130,8 @@
// transferReceipt.reportValidity();
}
saveForm();
return (
macAddressValid &&
customerName.value !== "" &&
@ -106,8 +150,36 @@
</button>
</div>
</header>
<% if (message) { %>
<div
role="alert"
class="alert alert-error w-[80vw] mx-auto mt-8"
style="z-index: 1000"
onclick="this.style.display = 'none'"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="stroke-current shrink-0 h-6 w-6"
fill="none"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span><%= message %></span>
</div>
<% } %>
<main>
<form class="flex justify-center" action="/register" method="post">
<form
class="flex justify-center"
action="/register"
method="post"
enctype="multipart/form-data"
>
<div class="w-[80vw]">
<div class="join-horizontal mt-8">
<div class="join-vertical justify-center">
@ -117,6 +189,14 @@
</p>
</div>
<br />
<button
class="btn btn-block btn-outline btn-error"
onclick="clearForm();event.preventDefault()"
>
Clear Form
</button>
<br />
<br />
<div class="join-vertical">
<div class="form-control">
<label class="label">
@ -167,11 +247,7 @@
network.
</p>
<div class="collapse collapse-arrow bg-base-200">
<input
type="checkbox"
name="my-accordion-1"
checked="checked"
/>
<input type="checkbox" checked="checked" />
<div class="collapse-title text-xl font-medium">iPhone</div>
<div class="collapse-content overflow-x-auto">
<div class="overflow-x-auto text-sm breadcrumbs">
@ -185,7 +261,7 @@
</div>
</div>
<div class="collapse collapse-arrow bg-base-200">
<input type="checkbox" name="my-accordion-1" />
<input type="checkbox" />
<div class="collapse-title text-xl font-medium">Redmi</div>
<div class="collapse-content overflow-x-auto">
<div class="overflow-x-auto text-sm breadcrumbs">
@ -198,7 +274,7 @@
</div>
</div>
<div class="collapse collapse-arrow bg-base-200">
<input type="checkbox" name="my-accordion-1" />
<input type="checkbox" />
<div class="collapse-title text-xl font-medium">Samsung</div>
<div class="collapse-content overflow-x-auto">
<div class="overflow-x-auto text-sm breadcrumbs">
@ -212,7 +288,7 @@
</div>
</div>
<div class="collapse collapse-arrow bg-base-200">
<input type="checkbox" name="my-accordion-1" />
<input type="checkbox" />
<div class="collapse-title text-xl font-medium">
Windows Laptop
</div>
@ -229,7 +305,7 @@
</div>
</div>
<div class="collapse collapse-arrow bg-base-200">
<input type="checkbox" name="my-accordion-1" />
<input type="checkbox" />
<div class="collapse-title text-xl font-medium">
Other Device
</div>
@ -260,6 +336,22 @@
</div>
</div>
<br />
<div class="join-vertical">
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">Is Device Roaming?</span>
<input
type="checkbox"
id="is_roaming"
name="is_roaming"
checked="checked"
class="checkbox"
oninput="setRoaming()"
/>
</label>
</div>
</div>
<br />
<br />
<div class="collapse bg-base-200">
<input type="checkbox" />
@ -268,8 +360,8 @@
</div>
<div class="collapse-content overflow-x-auto">
<p>
Please transfer MVR 100 to the following account and upload
the receipt below.
Please transfer the specified amount to the following account
and upload the receipt below.
</p>
<br />
<div class="overflow-x-auto text-sm">
@ -281,12 +373,16 @@
<li>
Account Name: <%- branding.bankDetails.accountName %>
</li>
<li id="amount">
Amount: <%- branding.price.roaming %> <%-
branding.price.currency %>
</li>
</ul>
<br />
<button
type="button"
class="btn btn-block btn-info"
onclick="navigator.clipboard.writeText('<%- branding.bankDetails.accountNumber %>')"
onclick="navigator.clipboard.writeText('<%- branding.bankDetails.accountNumber %>');event.target.textContent = 'Copied';setTimeout(() => { event.target.textContent = 'Copy Account Number'; }, 2000);"
>
Copy Account Number
</button>
@ -306,7 +402,7 @@
</p>
<br />
<div class="text-sm">
<ul>
<ol>
<li>Open BML Mobile App</li>
<li>Tap on "Transfer"</li>
<li>Tap on "Pay a new Contact"</li>
@ -322,7 +418,7 @@
Tap on "Send money" and continue to transfer like you
would normally
</li>
</ul>
</ol>
</div>
</div>
</div>
@ -359,4 +455,7 @@
</footer>
</main>
</body>
<script>
recoverForm();
</script>
</html>

27
test.js Normal file
View File

@ -0,0 +1,27 @@
require("dotenv").config()
const FormData = require('form-data');
const axios = require('axios').default;
const fs = require("fs")
const file = "./src/public/sarlink.jpg";
var formData = new FormData();
formData.append("photo", fs.createReadStream(file));
formData.append("message", "Sarlink test image");
const query = new URLSearchParams();
query.append("chat_id", process.env.TELEGRAM_CHAT_ID);
query.append("caption", "Sarlink test image");
// upload file to telegram using axios
axios.post(`${process.env.TG_BOTAPI}${process.env.TELEGRAM_BOT_TOKEN}/sendPhoto?${query.toString()}`, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
console.log(response.data)
})
.catch(error => {
console.error(error)
})