diff --git a/README.md b/README.md index e241aca..444ae3b 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,9 @@ The library is designed to be compatible with both module systems, so you can ch - `getEndpoint(network?: number | string, countriesList?: string | Array): { [key: string]: Array }` — Get an object of SMS endpoints (phone numbers) per country. - `sms(number?: boolean | string | number | Array, message?: string, network?: number | string, encodeMessage?: boolean, platform?: string): string` — Create an SMS URI based on the provided parameters. - `mms(number?: boolean | string | number | Array, message?: string, network?: number | string, encodeMessage?: boolean, platform?: string): string` — Create an MMS URI based on the provided parameters. -- `downloadMessage(hex: string, optionalFilename?: string): Promise` — Download a file with the encoded content as `.txms.txt` file in your working directory. +- `downloadMessage(hex: string | string[], optionalFilename?: string): Promise` — Download a file with the encoded content as `.txms.txt` file in your working directory. You can provide one hex transaction or an array of transactions (`.batch` will be prepended to suffix if batch is chosen and optional name not defined). + +Note: The `downloadMessage` function is asynchronous and returns a Promise. You can use the `await` keyword to wait for the Promise to resolve. The function will download a file with the encoded content as a `(.batch).txms.txt` file in your working directory. You can optionally provide a filename as the second parameter. It is designed to be used in Node.js environments as well as Browser. It is not designed to download high amount of files. if you prefer to do your own download flow, you can use the `encode` function and save the result to a file. ### Parameters @@ -157,6 +159,7 @@ The library is designed to be compatible with both module systems, so you can ch - `message` = the SMS message content. - `encodeMessage` (default: `true`) = whether to encode the message before using `encodeURIComponent`. - `platform` = the platform to use for the SMS URI. Currently supported: `ios`, `global`. Default: `global`. `ios` uses the `&body=`, while `global` uses the `?` for `?body=` parameter. +- `optionalFilename` = the optional filename for the downloaded file suffixed with `.txms.txt`. Filename is slugified. ## CLI @@ -169,17 +172,17 @@ npm i -g txms.js ### Getting started ```bash -txms {type} {value} {location} +txms {type} {value} {value1} ``` -- type: `encode` (`e`), `decode` (`d`), `getendpoint` (`g`), `sms`, `mms`, `download` (`dl`) -- value: message; network for getendpoint -- location: ISO 3166 Alpha-2 country/ies code/s for getendpoint +- type: `version` (`v`), `encode` (`e`), `decode` (`d`), `getendpoint` (`g`), `sms`, `mms`, `download` (`dl`) +- value: 1st parameter for the type +- value1: 2nd parameter for the type ### Piping ```bash -echo {value} | txms {type} {location} +echo {value} | txms {type} {value1} ``` ## Extending Aliases and Countries @@ -276,7 +279,7 @@ One MMS has 1600 characters. The MMS text limit is 5000 characters. MMS object h To send MMS, you can use two options: -- You can place the content as text document with extension `.txms` and send it to the same number. Each transaction can be divided with new line. You can place multiple `txms` files in one MMS. +- You can place the content as text document (text/plain) with extension `.txms.txt` and send it to the same number. Each transaction can be divided with new line. You can place multiple `txms` files into one MMS. - Place transaction(s) in the text message body and send it to the same number. Each transaction can be divided with new line. MMS has about the same price as SMS (in Slovakia), but the downside is that smartphone should have enabled the MMS service and the data are stored on 3rd party server. @@ -290,19 +293,19 @@ You're welcome to contribute in any capacity. We welcome: - Forking [this repository](https://github.com/bchainhub/txms.js/fork) +- Starring [this repository](https://github.com/bchainhub/txms.js/stargazers) - Opening a [pull request](https://github.com/bchainhub/txms.js/pulls) - Creating your own [SMS endpoint](#sms-endpoint) - Sending us some Øres / ₡ores: [cb7147879011ea207df5b35a24ca6f0859dcfb145999](https://blockindex.net/address/cb7147879011ea207df5b35a24ca6f0859dcfb145999) -- Starring this repository -To contribute, please follow the steps: +### To Contribute, Please Follow These Steps -1. Fork the repository. +1. [Fork the repository](https://github.com/bchainhub/txms.js/fork). 2. Create a new branch. 3. Make your changes. 4. Commit your changes. 5. Push your changes. -6. Open a pull request. +6. [Open a pull request](https://github.com/bchainhub/txms.js/pulls). Please ensure your code is well-documented and follows the project's coding standards. diff --git a/bin/txms b/bin/txms index a126d9f..170b105 100644 --- a/bin/txms +++ b/bin/txms @@ -5,9 +5,9 @@ import txms from '../dist/index.js'; if (process.stdin.isTTY) { const typ = process.argv[2]; const value = process.argv[3]; - const loc = process.argv[4]; + const value1 = process.argv[4]; - run(typ, value, loc); + run(typ, value, value1); } else { let content = ''; process.stdin.setEncoding('utf8'); @@ -19,33 +19,38 @@ if (process.stdin.isTTY) { let value = content; let typ = process.argv[2]; - let loc = process.argv[3]; + let value1 = process.argv[3]; if (!content) { value = process.argv[2]; typ = process.argv[3]; - loc = process.argv[4]; + value1 = process.argv[4]; } - run(typ, value, loc); + run(typ, value, value1); }); } -function run(typ, value, loc) { +function run(typ, value, value1) { if (!value) { process.stderr.write('value is required\n'); process.exit(1); } try { - if (typ === 'encode' || typ === 'e') { + if (typ === 'version' || typ === 'v') { + const packageJsonPath = join(__dirname, '../package.json'); + const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')); + const version = packageJson.version; + process.stdout.write(`TxMS version: ${version}\n`); + } else if (typ === 'encode' || typ === 'e') { const encoded = txms.encode(value); process.stdout.write(`${encoded}\n`); } else if (typ === 'decode' || typ === 'd') { const decoded = txms.decode(value); process.stdout.write(`${decoded}\n`); } else if (typ === 'getendpoint' || typ === 'g') { - const endpoint = txms.getEndpoint(value, loc); + const endpoint = txms.getEndpoint(value, value1); process.stdout.write(`${JSON.stringify(endpoint, null, 2)}\n`); } else if (typ === 'sms') { const sms = txms.sms(true, value); @@ -54,8 +59,13 @@ function run(typ, value, loc) { const mms = txms.mms(true, value); process.stdout.write(`${mms}\n`); } else if (typ === 'download' || typ === 'dl') { - const filename = txms.downloadMessage(value, loc); - process.stdout.write(`TxMS file was downloaded as "${filename}" in your working directory.\n`); + txms.downloadMessage(value, value1).then((filename) => { + process.stdout.write(`TxMS file was downloaded as "${filename}" in your working directory.\n`); + process.exit(0); + }).catch((err) => { + process.stderr.write(`${err.message}\n`); + process.exit(1); + }); } else { throw new Error('Invalid type specified.'); } diff --git a/package.json b/package.json index 1a5a8ab..9c18459 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "txms.js", - "version": "1.2.6", + "version": "1.2.7", "description": "Transaction messaging service protocol", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/index.ts b/src/index.ts index ec81ef8..7a7cc76 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,7 @@ export interface Transport { sms(number?: boolean | string | number | Array, message?: string, network?: number | string, encodeMessage?: boolean, platform?: string): string; mms(number?: boolean | string | number | Array, message?: string, network?: number | string, encodeMessage?: boolean, platform?: string): string; generateMessageUri(type: 'sms' | 'mms', number?: boolean | string | number | Array, message?: string, network?: number | string, encodeMessage?: boolean, platform?: string): string; - downloadMessage(hex: string, optionalFilename?: string): Promise; + downloadMessage(hex: string | string[], optionalFilename?: string): Promise; } export interface Error extends globalThis.Error { @@ -167,37 +167,60 @@ const txms: Transport = { return endpoint ? `${type}:${endpoint}${encodedMessage ? `${platform === 'ios' ? '&' : '?'}body=${encodedMessage}` : ''}` : `${type}:${platform === 'ios' ? '&' : '?'}body=${encodedMessage}`; }, - async downloadMessage(hex: string, optionalFilename?: string): Promise { - const encodedMessage = this.encode(hex); + async downloadMessage(hex: string | string[], optionalFilename?: string): Promise { + // If hex is an array, join the encoded messages with newlines + const encodedMessage = Array.isArray(hex) + ? hex.map(h => this.encode(h)).join('\n') + : this.encode(hex); let filename: string; - const cleanedHex = hex.startsWith('0x') ? hex.slice(2) : hex; + // Use the first hex string for filename derivation, regardless of array or string input + const cleanedHex = (Array.isArray(hex) ? hex[0] : hex).toLowerCase().startsWith('0x') + ? (Array.isArray(hex) ? hex[0] : hex).slice(2) + : (Array.isArray(hex) ? hex[0] : hex); if (cleanedHex.length < 12) { - filename = `${cleanedHex}.txms.txt`; + filename = cleanedHex; } else { const first6 = cleanedHex.slice(0, 6); const last6 = cleanedHex.slice(-6); - filename = `${first6}${last6}.txms.txt`; + filename = `${first6}${last6}`; } + // If the input is an array with more than one item and no optional filename, append .batch + if (Array.isArray(hex) && hex.length > 1 && !optionalFilename) { + filename = `${filename}.batch`; + } + + // Final filename composition if (optionalFilename) { filename = `${slugify(optionalFilename)}.txms.txt`; + } else { + filename = `${filename}.txms.txt`; } + // Node.js environment check + /* eslint-disable no-undef */ if (typeof process !== 'undefined' && process.versions && process.versions.node) { + // Node.js: Use 'fs' to write the file const fs = await import('fs'); fs.writeFileSync(filename, encodedMessage); - } else { + } else if (typeof window !== 'undefined' && typeof Blob !== 'undefined' && typeof document !== 'undefined') { + // Browser environment const blob = new Blob([encodedMessage], { type: 'text/plain;charset=utf-16' }); - const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = filename; - link.click(); + document.body.appendChild(link); // Append link to body + link.click(); // Trigger download + document.body.removeChild(link); // Clean up + } else { + throw new Error('Unsupported environment'); } + /* eslint-enable no-undef */ return filename; } + }; export default txms;