import 'dotenv/config'; const username = process.env.SMS_USERNAME; const password = process.env.SMS_PASSWORD ?? process.env.SMS_API_KEY; const sender = process.env.SMS_SENDER; const provider = (process.env.SMS_PROVIDER ?? 'trez').toLowerCase(); if (!username || !password || !sender) { console.error('Set SMS_USERNAME, SMS_PASSWORD (or SMS_API_KEY), and SMS_SENDER in .env'); process.exit(1); } const targets = process.argv.slice(2).length ? process.argv.slice(2) : ['09128081392']; const text = 'کد ورود منتایم: 123456'; const timeoutMs = Number.parseInt(process.env.SMS_TIMEOUT_MS ?? '20000', 10); function parseTrezResponse(body) { const trimmed = body.trim(); if (!trimmed) return { ok: true, reason: 'empty' }; const lower = trimmed.toLowerCase(); if (lower.includes('error') || lower.includes('fail') || lower.includes('خطا')) { return { ok: false, reason: trimmed }; } if (/^-?\d+$/.test(trimmed)) { const n = Number(trimmed); if (n === 1 || n > 1) return { ok: true, reason: trimmed }; return { ok: false, reason: `code ${trimmed}` }; } return { ok: true, reason: trimmed }; } async function sendViaTrez(mobile) { const baseUrl = (process.env.SMS_BASE_URL ?? 'http://smspanel.Trez.ir').replace(/\/$/, ''); const path = process.env.SMS_SEND_PATH ?? '/SendMessageWithCode.ashx'; const url = `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`; const res = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ PhoneNumber: sender, Username: username, Password: password, Mobile: mobile, Message: text, }).toString(), signal: AbortSignal.timeout(timeoutMs), }); const body = await res.text(); const parsed = parseTrezResponse(body); console.log( `mobile=${mobile} provider=trez http=${res.status} body=${JSON.stringify(body.trim())} ${parsed.ok ? 'OK' : 'FAILED'} (${parsed.reason})`, ); } async function sendVia0098(mobile) { const escapeXml = (value) => String(value) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); const soapBody = ` ${escapeXml(username)} ${escapeXml(password)} ${escapeXml(text)} ${escapeXml(mobile)} ${escapeXml(sender)} `; const res = await fetch('https://webservice.0098sms.com/service.asmx', { method: 'POST', headers: { 'Content-Type': 'text/xml; charset=utf-8', SOAPAction: 'http://tempuri.org/SendSMS', }, body: soapBody, signal: AbortSignal.timeout(timeoutMs), }); const body = await res.text(); const match = body.match(/]*>([^<]*)<\/SendSMSResult>/i); const code = match?.[1]?.trim() ?? '?'; const n = Number(code); const ok = Number.isFinite(n) ? n >= 0 : false; console.log( `mobile=${mobile} provider=0098 http=${res.status} RESULT=${code} ${ok ? 'OK' : 'FAILED'}`, ); } console.log(`SMS_PROVIDER=${provider}`); for (const mobile of targets) { if (provider === '0098') { await sendVia0098(mobile); } else { await sendViaTrez(mobile); } }