├── .babelrc.json ├── .eslintignore ├── .eslintrc.json ├── .github ├── FUNDING.yml └── workflows │ └── jekyll-gh-pages.yml ├── .gitignore ├── .gitkeep ├── .npmignore ├── .prettierignore ├── .prettierrc.json ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── SECURITY.md ├── dist ├── cjs │ ├── cli.d.ts │ ├── cli.js │ ├── data │ │ ├── countries.d.ts │ │ ├── countries.js │ │ ├── phones.d.ts │ │ └── phones.js │ ├── index.d.ts │ ├── index.js │ ├── login.d.ts │ ├── login.js │ ├── package.json │ ├── search.d.ts │ ├── search.js │ ├── verifyOtp.d.ts │ └── verifyOtp.js ├── cli.d.ts ├── cli.js ├── data │ ├── countries.d.ts │ ├── countries.js │ ├── phones.d.ts │ └── phones.js ├── index.d.ts ├── index.js ├── login.d.ts ├── login.js ├── search.d.ts ├── search.js ├── verifyOtp.d.ts └── verifyOtp.js ├── docs └── README.md ├── jest.config.ts ├── package-lock.json ├── package.json ├── src ├── cli.ts ├── data │ ├── continents.json │ ├── countries.json │ ├── countries.ts │ ├── languages.json │ ├── phones.json │ └── phones.ts ├── index.ts ├── json-to-pretty-yaml.d.ts ├── login.ts ├── search.ts └── verifyOtp.ts ├── test ├── 1-login.test.js ├── 2-verifyOtp.test.js ├── 3-search.test.js └── 4-bulkSearch.test.js ├── tsconfig.json └── typings └── index.d.ts /.babelrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | test 3 | dist 4 | build 5 | .truecallerjs/authkey.json 6 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], 7 | "parser": "@typescript-eslint/parser", 8 | "parserOptions": { 9 | "ecmaVersion": "latest", 10 | "sourceType": "module" 11 | }, 12 | "plugins": ["@typescript-eslint"], 13 | "rules": {} 14 | } 15 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: sumithemmadi 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | # liberapay: sumithemmadi 10 | # issuehunt: sumithemmadi 11 | otechie: # Replace with a single Otechie username 12 | custom: ["https://paypal.me/sumithemmadi"] 13 | -------------------------------------------------------------------------------- /.github/workflows/jekyll-gh-pages.yml: -------------------------------------------------------------------------------- 1 | # Sample workflow for building and deploying a Jekyll site to GitHub Pages 2 | name: Deploy Jekyll with GitHub Pages dependencies preinstalled 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ["docs"] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 19 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 20 | concurrency: 21 | group: "pages" 22 | cancel-in-progress: false 23 | 24 | jobs: 25 | # Build job 26 | build: 27 | runs-on: ubuntu-latest 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v3 31 | - name: Setup Pages 32 | uses: actions/configure-pages@v3 33 | - name: Build with Jekyll 34 | uses: actions/jekyll-build-pages@v1 35 | with: 36 | source: ./ 37 | destination: ./_site 38 | - name: Upload artifact 39 | uses: actions/upload-pages-artifact@v2 40 | 41 | # Deployment job 42 | deploy: 43 | environment: 44 | name: github-pages 45 | url: ${{ steps.deployment.outputs.page_url }} 46 | runs-on: ubuntu-latest 47 | needs: build 48 | steps: 49 | - name: Deploy to GitHub Pages 50 | id: deployment 51 | uses: actions/deploy-pages@v2 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .truecallerjs/authkey.json 3 | coverage 4 | test/authkey.json 5 | test/request.json 6 | -------------------------------------------------------------------------------- /.gitkeep: -------------------------------------------------------------------------------- 1 | src/ 2 | test/ 3 | docs/ 4 | dist/ 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | docs/ 2 | 3 | # Ignore source files 4 | src/ 5 | 6 | # Ignore development and configuration files 7 | node_modules/ 8 | coverage/ 9 | CODE_OF_CONDUCT.md 10 | SECURITY.md 11 | test/ 12 | .git 13 | .gitkeep 14 | .github 15 | .eslint* 16 | .prettier* 17 | 18 | jest.config.ts 19 | 20 | 21 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.md 2 | build 3 | dist 4 | node_modules -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct for https://github.com/sumithemmadi/truecallerjs 2 | 3 | ## Our Pledge 4 | 5 | We, as members, contributors, and maintainers of this repository, pledge to foster an open, inclusive, and respectful environment for everyone who engages with our project. We are dedicated to providing a harassment-free experience, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to a positive environment include: 10 | 11 | - Being respectful and considerate towards others. 12 | - Encouraging and supporting each other's ideas and contributions. 13 | - Providing and receiving constructive feedback with grace and openness. 14 | - Being empathetic and understanding towards differing perspectives. 15 | 16 | Examples of unacceptable behavior include: 17 | 18 | - Use of offensive, derogatory, or inappropriate language. 19 | - Harassment, trolling, or any form of personal attacks. 20 | - Publishing private information without explicit permission. 21 | - Engaging in any behavior that could be considered inappropriate or harmful. 22 | 23 | ## Responsibilities 24 | 25 | Project maintainers are responsible for upholding the standards of conduct within the repository. They have the right and duty to remove, edit, or reject comments, code, and other contributions that violate this Code of Conduct. 26 | 27 | ## Scope 28 | 29 | This Code of Conduct applies to all interactions within the repository, as well as to any public representation of the project. This includes comments, issues, pull requests, code reviews, and any other communication. 30 | 31 | ## Enforcement 32 | 33 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [Your Contact Email]. All complaints will be reviewed promptly and treated with confidentiality and respect. Project maintainers are obligated to respect the privacy and security of the reporter of any incident. 34 | 35 | ## Consequences 36 | 37 | Anyone found to be violating this Code of Conduct may face consequences, which can include: 38 | 39 | 1. **Warning**: A private, written warning from the project maintainers. 40 | 2. **Temporary Ban**: A temporary ban from participating in the repository. 41 | 3. **Permanent Ban**: A permanent ban from the repository and its related activities. 42 | 43 | Project maintainers will use their discretion in determining the appropriate consequences for each case, considering the severity and impact of the violation. 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Emmadi Sumith Kumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TruecallerJS 2 | 3 | 4 | 5 | [![NPM version](https://img.shields.io/npm/v/truecallerjs.svg)](https://www.npmjs.com/package/truecallerjs) 6 | [![GIT Stars](https://img.shields.io/github/stars/sumithemmadi/truecallerjs)](https://github.com/sumithemmadi/truecallerjs/) 7 | [![Download](https://img.shields.io/npm/dt/truecallerjs.svg)](https://github.com/sumithemmadi/truecallerjs) 8 | [![GitHub Sponsors](https://img.shields.io/github/sponsors/sumithemmadi)](https://github.com/sumithemmadi/truecallerjs) 9 | [![LICENSE](https://img.shields.io/npm/l/truecallerjs.svg)](https://github.com/sumithemmadi/truecallerjs/blob/main/LICENSE) 10 | [![Maintenance](https://img.shields.io/npms-io/maintenance-score/truecallerjs)](https://github.com/sumithemmadi/truecallerjs) 11 | [![Issues](https://img.shields.io/github/issues/sumithemmadi/truecallerjs)](https://github.com/sumithemmadi/truecallerjs/issues) 12 | 13 | Welcome to TruecallerJS! This is a library for retrieving phone number details using the Truecaller API. It provides a simple and convenient way to access information about phone numbers in your Node.js, JavaScript, and TypeScript projects. 14 | 15 | ## Description 16 | 17 | TruecallerJS is built to simplify the process of fetching phone number details. With this library, you can easily integrate Truecaller functionality into your Node.js, JavaScript, and TypeScript applications. It abstracts the complexities of interacting with the Truecaller API and provides a streamlined interface for fetching and processing phone number information. 18 | 19 | ## Features 20 | 21 | - **Phone Number Lookup**: Retrieve detailed information about a phone number, including the owner's name, location, and more. 22 | 23 | - **Support for Node.js, JavaScript, and TypeScript**: TruecallerJS can be used in Node.js projects, as well as in JavaScript and TypeScript applications. 24 | - **Simple and Lightweight**: TruecallerJS is designed to be easy to use and lightweight. 25 | 26 | ## Table of Contents 27 | 28 | - [TruecallerJS](#truecallerjs) 29 | - [Description](#description) 30 | - [Features](#features) 31 | - [Table of Contents](#table-of-contents) 32 | - [Installation](#installation) 33 | - [Command Line Usage](#command-line-usage) 34 | - [Limitations](#limitations) 35 | - [Usage](#usage) 36 | - [Simple Example](#simple-example) 37 | - [Bulk Search on Multiple Phone Numbers](#bulk-search-on-multiple-phone-numbers) 38 | - [Disclaimer](#disclaimer) 39 | - [Contributing](#contributing) 40 | - [License](#license) 41 | - [Acknowledgments](#acknowledgments) 42 | 43 | ## Installation 44 | 45 | You can install TruecallerJS using npm: 46 | 47 | ```bash 48 | npm install truecallerjs 49 | ``` 50 | 51 | To use TruecallerJS from the command line 52 | 53 | ```bash 54 | npm install -g truecallerjs 55 | ``` 56 | 57 | > **Note**: If you are using a version of `truecallerjs` that is older than [1.1.2](https://github.com/sumithemmadi/truecallerjs/tree/truecallerjs-v1.1.2), we recommend referring to the [truecallerjs-v1.1.2](https://github.com/sumithemmadi/truecallerjs/tree/truecallerjs-v1.1.2) documentation for instructions. 58 | > **Note**: If you are using `truecallerjs` version from [1.1.3](https://github.com/sumithemmadi/truecallerjs/tree/truecallerjs-v1.1.2) to [1.1.5](https://github.com/sumithemmadi/truecallerjs/tree/truecallerjs-v1.1.5), please refer to the [truecallerjs-v1.1.5](https://github.com/sumithemmadi/truecallerjs/tree/truecallerjs-v1.1.5) documentation for instructions. 59 | 60 | ## Command Line Usage 61 | 62 | To use TruecallerJS from the command line, you can run the `truecallerjs` command followed by the desired options and arguments. 63 | 64 | Here are some examples of the available options: 65 | 66 | - `truecallerjs login`: Use this command to log in to your Truecaller account. 67 | - `truecallerjs -s [number]`: Use this command to search for a phone number and retrieve the caller name and related information. 68 | - `truecallerjs --bulksearch, --bs` command is used to performing bulk number searches using the Truecaller service. It allows you to search for multiple phone numbers at once, making it convenient for processing large sets of phone numbers in a single request. 69 | 70 | - `truecallerjs --bulksearch, --bs`: Use this command to perform a bulk number search. 71 | - Additional options include `--raw`, `--name`, `--email`, `--json`, `--xml`, `--yaml`, `--text`, `--nc`, `--installationid`, `--verbose`, and `--help`. 72 | 73 | For example: 74 | 75 | ```bash 76 | ~$ truecallerjs -s +9199123456789 --json 77 | { 78 | ... 79 | "name":"Sumith Emmadi" 80 | ... 81 | } 82 | 83 | ~$ truecallerjs -s +9199123456789 --name 84 | Name : Sumith Emmadi 85 | ``` 86 | 87 | Example for bulk search 88 | 89 | ```bash 90 | truecallerjs --bulksearch ,,,..., 91 | ``` 92 | 93 | Replace `, , ..., ` with the actual phone numbers you want to search. Separate each phone number with a comma. 94 | 95 | ```bash 96 | ~$ truecallerjs --bs 9912345678,+14051234567,+919987654321 97 | ``` 98 | 99 | > **Note** : If the country code is not specified for a phone number, it will default to using your own country code. 100 | 101 | ### Limitations 102 | 103 | Please note the following limitations when using the `--bulksearch` option: 104 | 105 | 1. Maximum Number of Phone Numbers: The tool supports searching 30 or fewer phone numbers at once in a single request. If you exceed this limit, you may need to split your input into multiple requests. 106 | 107 | 2. Formatting: Ensure that the phone numbers are correctly formatted and do not contain any additional characters or spaces. The tool expects the phone numbers to be provided in a comma-separated format. 108 | 109 | ## Usage 110 | 111 | To use the project, start by installing the `truecallerjs` package via npm: 112 | 113 | ```bash 114 | npm install truecallerjs 115 | ``` 116 | 117 | ### Simple Example 118 | 119 | Here's a basic example of how to perform a normal search for a phone number: 120 | 121 | ```ts 122 | import truecallerjs, { SearchData, Format } from "truecallerjs"; 123 | 124 | async function performTruecallerSearch(): Promise { 125 | const searchData: SearchData = { 126 | number: "9912345678", 127 | countryCode: "IN", 128 | installationId: "a1k07--Vgdfyvv_rftf5uuudhuhnkljyvvtfftjuhbuijbhug", 129 | }; 130 | 131 | try { 132 | const response: Format = await truecallerjs.search(searchData); 133 | console.log(response.json()); 134 | 135 | // Additional response methods: 136 | // console.log(response.xml()); 137 | // console.log(response.yaml()); 138 | // console.log(response.text()); 139 | 140 | // Example of available data from the response: 141 | console.log(response.getName()); // "Sumith Emmadi" 142 | console.log(response.getAlternateName()); // "sumith" 143 | console.log(response.getAddresses()); // {....} 144 | console.log(response.getEmailId()); // example@domain.com 145 | console.log(response.getCountryDetails()); // {...} 146 | } catch (error) { 147 | console.error("Error occurred:", error); 148 | } 149 | } 150 | 151 | performTruecallerSearch(); 152 | ``` 153 | 154 | In the above example, the `truecallerjs` package is used to search for a phone number. The `search_data` object contains the necessary parameters, including the number, country code, and installation ID. The response from the `truecallerjs.search()` function provides various methods to access the returned data. 155 | 156 | > **Note** : Make sure to log in using the `truecallerjs login` command and obtain your installation ID using the `truecallerjs -i` command. 157 | 158 | ### Bulk Search on Multiple Phone Numbers 159 | 160 | The `truecallerjs` package also supports bulk search on multiple phone numbers: 161 | 162 | ```ts 163 | import truecallerjs, { BulkSearchData, Format } from "truecallerjs"; 164 | 165 | async function performBulkTruecallerSearch(): Promise { 166 | const countryCode: string = "IN"; 167 | const installationId: string = "a1k07--Vgdfyvv_rftf5uuudhuhnkljyvvtfftjuhbuijbhug"; 168 | const phoneNumbers: string = "+9912345678,+14051234567,+919987654321"; 169 | 170 | try { 171 | const response: BulkSearchData = await truecallerjs.bulkSearch(phoneNumbers, countryCode, installationId); 172 | console.log(response); 173 | } catch (error) { 174 | console.error("Error occurred:", error); 175 | } 176 | } 177 | 178 | performBulkTruecallerSearch(); 179 | 180 | ``` 181 | 182 | In this example, the `truecallerjs.bulkSearch()` function is used to perform bulk searches on multiple phone numbers. The `phoneNumbers` parameter should contain the phone numbers separated by commas. The `countryCode` and `installationId` parameters are used to specify the default country code and installation ID, respectively. 183 | 184 | > **Note** : Make sure to log in using the `truecallerjs login` command and obtain your installation ID using the `truecallerjs -i` command. 185 | 186 | For more details and additional functionalities, please refer to the [documentation](https://github.com/sumithemmadi/truecallerjs/tree/main/docs), including the process for logging in and obtaining the installation ID. 187 | 188 | ## Disclaimer 189 | 190 | The `truecallerjs` tool is not an official Truecaller product. It is a custom script developed by [Sumith Emmadi](https://github.com/sumithemmadi), and its functionality is dependent on the Truecaller service. Please use this tool responsibly and in compliance with the terms of service of Truecaller. 191 | 192 | For more information and support, please contact [Sumith Emmadi](https://github.com/sumithemmadi) at . 193 | 194 | ## Contributing 195 | 196 | Contributions to the `truecallerjs` are not only welcome but highly encouraged! 197 | 198 | 1. Fork this repository `git clone https://github.com/sumithemmadi/truecallerjs.git` 199 | 2. Create a new branch for your contribution. 200 | 3. Add your content in the appropriate folder or create a new file. 201 | 4. Commit your changes and push them to your forked repository. 202 | 5. Open a pull request, explaining the nature of your contribution. 203 | 204 | Please note that all contributions should align with the spirit of the repository and be suitable for all audiences. Offensive or inappropriate content will not be accepted. 205 | 206 | ## License 207 | 208 | TruecallerJS is open source and licensed under the MIT License. See the LICENSE file for more information. 209 | 210 | ## 💝 Sponsor and support me 211 | 212 | If you find my project helpful or inspiring, consider supporting me through GitHub Sponsors. Your sponsorship helps me dedicate more time and effort to open source development and creating impactful projects. 213 | 214 | [:heart: Sponsor me on github](https://github.com/sponsors/sumithemmadi?o=sd&sc=t) 215 | 216 | Buy Me a Coffee at ko-fi.com 217 | 218 | sumithemmadi

219 | 220 | ### 💖 Sponsors 221 | 222 | [![Sponsors](https://sumithemmadi.github.io/sponsors.svg)](https://github.com/sponsors/sumithemmadi/) 223 | 224 | - I want to extend my sincere gratitude to all my sponsors for their generous support. 225 | 226 | ## Acknowledgments 227 | 228 | Thank you for choosing TruecallerJS! I hope it helps you retrieve phone number details efficiently. 229 | 230 | Repository: 231 | [https://github.com/sumithemmadi/truecallerjs.git](https://github.com/sumithemmadi/truecallerjs.git) 232 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ## Security Policy 2 | 3 | ### Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 2.2.x | :white_check_mark: | 8 | | 2.1.x | :x: | 9 | | 2.0.x | :x: | 10 | | < 1.1.x | :x: | 11 | | < 1.0.x | :x: | 12 | 13 | ### Reporting a Vulnerability 14 | 15 | To report a security vulnerability, please email [sumithemmadi244@gmail.com](mailto:sumithemmadi244@gmail.com). Provide a detailed description, steps to reproduce, and PoC if possible. 16 | 17 | I will acknowledge receipt within 7 days and investigate. If valid, I will release a fix and coordinate disclosure responsibly. 18 | 19 | ### Security Updates and Support 20 | 21 | We only provide security updates for version 2.1.x. Upgrade to the latest supported version for protection. 22 | 23 | Thank you for your contributions to a safer environment. 24 | -------------------------------------------------------------------------------- /dist/cjs/cli.d.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | export {}; 3 | -------------------------------------------------------------------------------- /dist/cjs/data/countries.d.ts: -------------------------------------------------------------------------------- 1 | interface CountryData { 2 | name: string; 3 | native: string; 4 | phone: number[]; 5 | continent: string; 6 | capital: string; 7 | currency: string[]; 8 | languages: string[]; 9 | flag: string; 10 | flagURL: string; 11 | } 12 | interface Countries { 13 | [countryCode: string]: CountryData; 14 | } 15 | declare const countries: Countries; 16 | export { countries }; 17 | -------------------------------------------------------------------------------- /dist/cjs/data/phones.d.ts: -------------------------------------------------------------------------------- 1 | declare const device: { 2 | manufacturer: string; 3 | model: string; 4 | }; 5 | export { device }; 6 | -------------------------------------------------------------------------------- /dist/cjs/data/phones.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // MIT License 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | exports.device = void 0; 5 | // Copyright (c) 2021 Emmadi Sumith Kumar 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | const phones_list = [ 22 | { 23 | manufacturer: "Xiaomi", 24 | model: "M2010J19SG", 25 | }, 26 | { 27 | manufacturer: "Xiaomi", 28 | model: "POCO F1", 29 | }, 30 | { 31 | manufacturer: "Xiaomi", 32 | model: "Redmi 9A", 33 | }, 34 | { 35 | manufacturer: "Xiaomi", 36 | model: "Xiaomi Mi 4", 37 | }, 38 | { 39 | manufacturer: "Xiaomi", 40 | model: "Redmi Note 10 pro", 41 | }, 42 | { 43 | manufacturer: "Xiaomi", 44 | model: "Redmi Note 10", 45 | }, 46 | { 47 | manufacturer: "Xiaomi", 48 | model: "Xiaomi Redmi 1S", 49 | }, 50 | { 51 | manufacturer: "Xiaomi", 52 | model: "Xiaomi Mi 10T", 53 | }, 54 | { 55 | manufacturer: "Xiaomi", 56 | model: "Xiaomi Redmi 6 Pro", 57 | }, 58 | { 59 | manufacturer: "Xiaomi", 60 | model: "Xiaomi Redmi Y3", 61 | }, 62 | { 63 | manufacturer: "Xiaomi", 64 | model: "Xiaomi Redmi 9 Prime", 65 | }, 66 | { 67 | manufacturer: "Xiaomi", 68 | model: "Redmi Note 7", 69 | }, 70 | { 71 | manufacturer: "Vivo", 72 | model: "Vivo Y33s", 73 | }, 74 | { 75 | manufacturer: "Vivo", 76 | model: "Vivo V21 5G", 77 | }, 78 | { 79 | manufacturer: "Vivo", 80 | model: "Vivo Y20T", 81 | }, 82 | { 83 | manufacturer: "Vivo", 84 | model: "Vivo Y73 2021", 85 | }, 86 | { 87 | manufacturer: "Vivo", 88 | model: "Vivo X60", 89 | }, 90 | { 91 | manufacturer: "Vivo", 92 | model: "Vivo X70 Pro 5G", 93 | }, 94 | { 95 | manufacturer: "Vivo", 96 | model: "Vivo U3x", 97 | }, 98 | { 99 | manufacturer: "Vivo", 100 | model: "Vivo V20 Pro", 101 | }, 102 | { 103 | manufacturer: "Vivo", 104 | model: "Vivo Y21 2021", 105 | }, 106 | { 107 | manufacturer: "Vivo", 108 | model: "Vivo Y53s", 109 | }, 110 | { 111 | manufacturer: "Vivo", 112 | model: "Vivo S12 Pro", 113 | }, 114 | { 115 | manufacturer: "Vivo", 116 | model: "Vivo V21e 5G", 117 | }, 118 | { 119 | manufacturer: "OnePlus", 120 | model: "OnePlus Nord CE 5G", 121 | }, 122 | { 123 | manufacturer: "OnePlus", 124 | model: "OnePlus 9 Pro", 125 | }, 126 | { 127 | manufacturer: "OnePlus", 128 | model: "OnePlus 8T", 129 | }, 130 | { 131 | manufacturer: "OnePlus", 132 | model: "OnePlus 9", 133 | }, 134 | { 135 | manufacturer: "OnePlus", 136 | model: "OnePlus 7T", 137 | }, 138 | { 139 | manufacturer: "OnePlus", 140 | model: "OnePlus 6T", 141 | }, 142 | { 143 | manufacturer: "OnePlus", 144 | model: "OnePlus Nord 2", 145 | }, 146 | { 147 | manufacturer: "OnePlus", 148 | model: "OnePlus 7 Pro", 149 | }, 150 | { 151 | manufacturer: "OnePlus", 152 | model: "OnePlus Nord", 153 | }, 154 | { 155 | manufacturer: "Realme", 156 | model: "RMX2185", 157 | }, 158 | { 159 | manufacturer: "Realme", 160 | model: "Realme GT Neo2 5G", 161 | }, 162 | { 163 | manufacturer: "Realme", 164 | model: "Realme 8 5G", 165 | }, 166 | { 167 | manufacturer: "Realme", 168 | model: "Realme C11 2021", 169 | }, 170 | { 171 | manufacturer: "Realme", 172 | model: "Realme GT", 173 | }, 174 | { 175 | manufacturer: "Realme", 176 | model: "Realme Narzo 30", 177 | }, 178 | { 179 | manufacturer: "Realme", 180 | model: "Realme Q3i 5G", 181 | }, 182 | { 183 | manufacturer: "Realme", 184 | model: "Realme 8s 5G", 185 | }, 186 | { 187 | manufacturer: "Realme", 188 | model: "Realme 8i", 189 | }, 190 | { 191 | manufacturer: "Realme", 192 | model: "Realme Narzo 50A", 193 | }, 194 | { 195 | manufacturer: "Realme", 196 | model: "Realme C21Y", 197 | }, 198 | { 199 | manufacturer: "Oppo", 200 | model: "OPPO A55", 201 | }, 202 | { 203 | manufacturer: "Oppo", 204 | model: "OPPO A74 5G", 205 | }, 206 | { 207 | manufacturer: "Oppo", 208 | model: "OPPO A53", 209 | }, 210 | { 211 | manufacturer: "Oppo", 212 | model: "OPPO A31", 213 | }, 214 | { 215 | manufacturer: "Oppo", 216 | model: "OPPO A12", 217 | }, 218 | { 219 | manufacturer: "Oppo", 220 | model: "OPPO Reno6 Pro", 221 | }, 222 | { 223 | manufacturer: "Oppo", 224 | model: "OPPO Reno6", 225 | }, 226 | { 227 | manufacturer: "Oppo", 228 | model: "OPPO F19 Pro", 229 | }, 230 | { 231 | manufacturer: "Oppo", 232 | model: "OPPO F19s", 233 | }, 234 | { 235 | manufacturer: "Oppo", 236 | model: "Oppo F19 Pro+", 237 | }, 238 | { 239 | manufacturer: "Oppo", 240 | model: "Oppo A33", 241 | }, 242 | { 243 | manufacturer: "Oppo", 244 | model: "Oppo Reno 3 Pro", 245 | }, 246 | { 247 | manufacturer: "Oppo", 248 | model: "Oppo Reno 4 Pro", 249 | }, 250 | { 251 | manufacturer: "Oppo", 252 | model: "Oppo Find X2", 253 | }, 254 | { 255 | manufacturer: "Oppo", 256 | model: "OPPO F15", 257 | }, 258 | { 259 | manufacturer: "Oppo", 260 | model: "OPPO Reno 2F", 261 | }, 262 | { 263 | manufacturer: "Oppo", 264 | model: "OPPO K3", 265 | }, 266 | { 267 | manufacturer: "Oppo", 268 | model: "OPPO A9", 269 | }, 270 | { 271 | manufacturer: "Oppo", 272 | model: "OPPO A1k", 273 | }, 274 | { 275 | manufacturer: "Oppo", 276 | model: "OPPO A5s", 277 | }, 278 | { 279 | manufacturer: "Samsung", 280 | model: "Samsung Galaxy M31s", 281 | }, 282 | { 283 | manufacturer: "Samsung", 284 | model: "Samsung Galaxy M32", 285 | }, 286 | { 287 | manufacturer: "Samsung", 288 | model: "Samsung Galaxy F62", 289 | }, 290 | { 291 | manufacturer: "Samsung", 292 | model: "Samsung Galaxy M52 5G", 293 | }, 294 | { 295 | manufacturer: "Samsung", 296 | model: "Samsung Galaxy M12", 297 | }, 298 | { 299 | manufacturer: "Samsung", 300 | model: "Samsung Galaxy M51", 301 | }, 302 | { 303 | manufacturer: "Samsung", 304 | model: "Samsung Galaxy F12", 305 | }, 306 | { 307 | manufacturer: "Samsung", 308 | model: "Samsung Galaxy F22", 309 | }, 310 | { 311 | manufacturer: "Samsung", 312 | model: "Samsung Galaxy A52", 313 | }, 314 | { 315 | manufacturer: "Samsung", 316 | model: "Samsung Galaxy S20 FE 5G", 317 | }, 318 | { 319 | manufacturer: "Samsung", 320 | model: "Samsung Galaxy M52", 321 | }, 322 | { 323 | manufacturer: "Samsung", 324 | model: "Samsung Galaxy M62", 325 | }, 326 | { 327 | manufacturer: "Samsung", 328 | model: "Samsung Galaxy S21 Ultra", 329 | }, 330 | { 331 | manufacturer: "Samsung", 332 | model: "Samsung Galaxy A52s 5G", 333 | }, 334 | { 335 | manufacturer: "Samsung", 336 | model: "Samsung Galaxy S21", 337 | }, 338 | { 339 | manufacturer: "Samsung", 340 | model: "Samsung Galaxy M21 2021", 341 | }, 342 | { 343 | manufacturer: "Samsung", 344 | model: "Samsung Galaxy F42", 345 | }, 346 | { 347 | manufacturer: "Samsung", 348 | model: "Samsung Galaxy A12", 349 | }, 350 | { 351 | manufacturer: "Samsung", 352 | model: "Samsung Galaxy F41", 353 | }, 354 | { 355 | manufacturer: "Samsung", 356 | model: "Samsung Galaxy M01 Core", 357 | }, 358 | ]; 359 | const getRandomDevice = () => { 360 | const randomIndex = Math.floor(Math.random() * phones_list.length); 361 | return phones_list[randomIndex]; 362 | }; 363 | const device = getRandomDevice(); 364 | exports.device = device; 365 | -------------------------------------------------------------------------------- /dist/cjs/index.d.ts: -------------------------------------------------------------------------------- 1 | import { login as loginFunction } from "./login.js"; 2 | import { verifyOtp as verifyOtpFunction } from "./verifyOtp.js"; 3 | import { search as searchFunction, bulkSearch as bulkSearchFunction } from "./search.js"; 4 | export declare const login: typeof loginFunction; 5 | export declare const verifyOtp: typeof verifyOtpFunction; 6 | export declare const search: typeof searchFunction; 7 | export declare const bulkSearch: typeof bulkSearchFunction; 8 | declare const truecallerjs: { 9 | login: typeof loginFunction; 10 | verifyOtp: typeof verifyOtpFunction; 11 | search: typeof searchFunction; 12 | bulkSearch: typeof bulkSearchFunction; 13 | }; 14 | export default truecallerjs; 15 | -------------------------------------------------------------------------------- /dist/cjs/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // MIT License 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | exports.bulkSearch = exports.search = exports.verifyOtp = exports.login = void 0; 5 | // Copyright (c) 2021 Emmadi Sumith Kumar 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | const login_js_1 = require("./login.js"); 22 | const verifyOtp_js_1 = require("./verifyOtp.js"); 23 | const search_js_1 = require("./search.js"); 24 | exports.login = login_js_1.login; 25 | exports.verifyOtp = verifyOtp_js_1.verifyOtp; 26 | exports.search = search_js_1.search; 27 | exports.bulkSearch = search_js_1.bulkSearch; 28 | const truecallerjs = { 29 | login: exports.login, 30 | verifyOtp: exports.verifyOtp, 31 | search: exports.search, 32 | bulkSearch: exports.bulkSearch, 33 | }; 34 | exports.default = truecallerjs; 35 | -------------------------------------------------------------------------------- /dist/cjs/login.d.ts: -------------------------------------------------------------------------------- 1 | interface LoginResponse { 2 | status: number; 3 | message: string; 4 | domain: string; 5 | parsedPhoneNumber: number; 6 | parsedCountryCode: string; 7 | requestId: string; 8 | method: string; 9 | tokenTtl: number; 10 | } 11 | /** 12 | * Login to Truecaller. 13 | * 14 | * @param {string} phoneNumber - Phone number in international format. 15 | * @returns {Promise} - Promise that resolves to the login response containing the requestId used for OTP verification. 16 | */ 17 | declare function login(phoneNumber: string): Promise; 18 | export { login }; 19 | -------------------------------------------------------------------------------- /dist/cjs/login.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // MIT License 3 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 4 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 5 | return new (P || (P = Promise))(function (resolve, reject) { 6 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 7 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 8 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 9 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 10 | }); 11 | }; 12 | var __importDefault = (this && this.__importDefault) || function (mod) { 13 | return (mod && mod.__esModule) ? mod : { "default": mod }; 14 | }; 15 | Object.defineProperty(exports, "__esModule", { value: true }); 16 | exports.login = void 0; 17 | // Copyright (c) 2021 Emmadi Sumith Kumar 18 | // Permission is hereby granted, free of charge, to any person obtaining a copy 19 | // of this software and associated documentation files (the "Software"), to deal 20 | // in the Software without restriction, including without limitation the rights 21 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | // copies of the Software, and to permit persons to whom the Software is 23 | // furnished to do so, subject to the following conditions: 24 | // The above copyright notice and this permission notice shall be included in all 25 | // copies or substantial portions of the Software. 26 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | // SOFTWARE. 33 | const axios_1 = __importDefault(require("axios")); 34 | const awesome_phonenumber_1 = require("awesome-phonenumber"); 35 | const phones_js_1 = require("./data/phones.js"); 36 | function generateRandomString(length) { 37 | let result = ""; 38 | const characters = "abcdefghijklmnopqrstuvwxyz0123456789"; 39 | const charactersLength = characters.length; 40 | for (let i = 0; i < length; i++) { 41 | result += characters.charAt(Math.floor(Math.random() * charactersLength)); 42 | } 43 | return result; 44 | } 45 | /** 46 | * Login to Truecaller. 47 | * 48 | * @param {string} phoneNumber - Phone number in international format. 49 | * @returns {Promise} - Promise that resolves to the login response containing the requestId used for OTP verification. 50 | */ 51 | function login(phoneNumber) { 52 | return __awaiter(this, void 0, void 0, function* () { 53 | const pn = (0, awesome_phonenumber_1.parsePhoneNumber)(phoneNumber); 54 | if (!(pn === null || pn === void 0 ? void 0 : pn.valid)) { 55 | throw new Error("Invalid phone number."); 56 | } 57 | const postUrl = "https://account-asia-south1.truecaller.com/v2/sendOnboardingOtp"; 58 | const data = { 59 | countryCode: pn.regionCode, 60 | dialingCode: pn.countryCode, 61 | installationDetails: { 62 | app: { 63 | buildVersion: 5, 64 | majorVersion: 11, 65 | minorVersion: 7, 66 | store: "GOOGLE_PLAY", 67 | }, 68 | device: { 69 | deviceId: generateRandomString(16), 70 | language: "en", 71 | manufacturer: phones_js_1.device.manufacturer, 72 | model: phones_js_1.device.model, 73 | osName: "Android", 74 | osVersion: "10", 75 | mobileServices: ["GMS"], 76 | }, 77 | language: "en", 78 | }, 79 | phoneNumber: pn.number.significant, 80 | region: "region-2", 81 | sequenceNo: 2, 82 | }; 83 | const options = { 84 | method: "POST", 85 | headers: { 86 | "content-type": "application/json; charset=UTF-8", 87 | "accept-encoding": "gzip", 88 | "user-agent": "Truecaller/11.75.5 (Android;10)", 89 | clientsecret: "lvc22mp3l1sfv6ujg83rd17btt", 90 | }, 91 | url: postUrl, 92 | data, 93 | }; 94 | const res = yield (0, axios_1.default)(options); 95 | return res.data; 96 | }); 97 | } 98 | exports.login = login; 99 | -------------------------------------------------------------------------------- /dist/cjs/package.json: -------------------------------------------------------------------------------- 1 | {"type": "commonjs"} 2 | -------------------------------------------------------------------------------- /dist/cjs/search.d.ts: -------------------------------------------------------------------------------- 1 | interface Address { 2 | city: string; 3 | countryCode: string; 4 | timeZone: string; 5 | type: string; 6 | } 7 | interface InternetAddress { 8 | id: string; 9 | service: string; 10 | caption: string; 11 | type: string; 12 | } 13 | interface CountryDetails { 14 | name: string; 15 | native: string; 16 | phone: number[]; 17 | continent: string; 18 | capital: string; 19 | currency: string[]; 20 | languages: string[]; 21 | flag: string; 22 | flagURL: string; 23 | } 24 | interface Data { 25 | name?: string; 26 | altName?: string; 27 | addresses?: Address[]; 28 | internetAddresses?: InternetAddress[]; 29 | } 30 | interface SearchData { 31 | number: string; 32 | countryCode: string; 33 | installationId: string; 34 | } 35 | interface BulkSearchData { 36 | data: Data[]; 37 | } 38 | declare class Format { 39 | private data; 40 | constructor(data: BulkSearchData); 41 | json(): BulkSearchData; 42 | xml(color?: boolean): string; 43 | yaml(color?: boolean): string; 44 | text(color?: boolean, space?: boolean): string; 45 | getName(): string; 46 | getAlternateName(): string; 47 | getAddresses(): Address[]; 48 | getEmailId(): string; 49 | getCountryDetails(): CountryDetails; 50 | } 51 | /** 52 | * Searching phone number on truecallerjs 53 | * @var response => {...} 54 | * @method response.json(color) JSON response. 55 | * @method response.xml(color) XML output. 56 | * @method response.yaml(color) YAML output. 57 | * @method response.html(color) HTML output. 58 | * @method response.text(color,space) JSON response. 59 | * @method response.getName() => "Sumith Emmadi" 60 | * @method response.getAlternateName() => "sumith" 61 | * @method response.getAddresses() => {....} 62 | * @method response.getEmailId() => sumithemmadi244@gmail.com 63 | * @method response.getCountryDetails() => {...} 64 | * @name search 65 | * @function truecallerjs.search(search_data) 66 | * @return {Object} It contains details of the phone number 67 | */ 68 | declare function search(searchData: SearchData): Promise; 69 | /** 70 | * Bulk search on truecallerjs 71 | * @name bulkSearch 72 | * @function truecallerjs.bulkSearch(phoneNumbers,countryCode,installationId) 73 | * @param {String} phoneNumbers phone number separted with coma. 74 | * @param {String} installationId 6-digits OTP . 75 | * @return {Object} It contains phone numbers information in a array 76 | */ 77 | declare function bulkSearch(phoneNumbers: string, regionCode: string, installationId: string): Promise; 78 | export { search, bulkSearch }; 79 | -------------------------------------------------------------------------------- /dist/cjs/search.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // MIT License 3 | var __importDefault = (this && this.__importDefault) || function (mod) { 4 | return (mod && mod.__esModule) ? mod : { "default": mod }; 5 | }; 6 | Object.defineProperty(exports, "__esModule", { value: true }); 7 | exports.bulkSearch = exports.search = void 0; 8 | // Copyright (c) 2021 Emmadi Sumith Kumar 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | const axios_1 = __importDefault(require("axios")); 25 | const awesome_phonenumber_1 = require("awesome-phonenumber"); 26 | const xml2js_1 = require("xml2js"); 27 | const json_to_plain_text_1 = require("json-to-plain-text"); 28 | const json_to_pretty_yaml_1 = require("json-to-pretty-yaml"); 29 | const countries_js_1 = require("./data/countries.js"); 30 | class Format { 31 | constructor(data) { 32 | this.data = data; 33 | } 34 | json() { 35 | return this.data; 36 | } 37 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 38 | xml(color = false) { 39 | const builder = new xml2js_1.Builder(); 40 | const xml = builder.buildObject(JSON.parse(JSON.stringify(this.json()))); 41 | return xml; 42 | } 43 | yaml(color = false) { 44 | return (0, json_to_pretty_yaml_1.stringify)(JSON.parse(JSON.stringify(this.json())), color); 45 | } 46 | text(color = false, space = false) { 47 | const options = { 48 | color: color, 49 | spacing: space, 50 | squareBracketsForArray: false, 51 | doubleQuotesForKeys: false, 52 | doubleQuotesForValues: false, 53 | }; 54 | return (0, json_to_plain_text_1.jsonToPlainText)(JSON.parse(JSON.stringify(this.json())), options); 55 | } 56 | getName() { 57 | var _a, _b; 58 | return ((_b = (_a = this.json()) === null || _a === void 0 ? void 0 : _a.data[0]) === null || _b === void 0 ? void 0 : _b.name) || "unknown name"; 59 | } 60 | getAlternateName() { 61 | var _a, _b; 62 | return ((_b = (_a = this.json()) === null || _a === void 0 ? void 0 : _a.data[0]) === null || _b === void 0 ? void 0 : _b.altName) || "no alternate name"; 63 | } 64 | getAddresses() { 65 | var _a, _b; 66 | return ((_b = (_a = this.json()) === null || _a === void 0 ? void 0 : _a.data[0]) === null || _b === void 0 ? void 0 : _b.addresses) || []; 67 | } 68 | getEmailId() { 69 | var _a, _b, _c; 70 | const data = (_a = this.json()) === null || _a === void 0 ? void 0 : _a.data; 71 | if (data && data.length > 0) { 72 | const internetAddresses = (_b = data[0]) === null || _b === void 0 ? void 0 : _b.internetAddresses; 73 | if (internetAddresses && internetAddresses.length > 0) { 74 | const id = (_c = internetAddresses[0]) === null || _c === void 0 ? void 0 : _c.id; 75 | if (id) { 76 | return id; 77 | } 78 | } 79 | } 80 | return "unknown email"; 81 | } 82 | getCountryDetails() { 83 | var _a, _b, _c; 84 | const data = (_a = this.json()) === null || _a === void 0 ? void 0 : _a.data; 85 | if (data && data.length > 0) { 86 | const addresses = (_b = data[0]) === null || _b === void 0 ? void 0 : _b.addresses; 87 | if (addresses && addresses.length > 0) { 88 | const countryCode = (_c = addresses[0]) === null || _c === void 0 ? void 0 : _c.countryCode; 89 | if (countryCode) { 90 | return countries_js_1.countries[countryCode]; 91 | } 92 | } 93 | } 94 | return { 95 | name: "unknown", 96 | native: "unknwon", 97 | phone: [], 98 | continent: "unknwon", 99 | capital: "unknwon", 100 | currency: ["unknwon"], 101 | languages: ["unknwon"], 102 | flag: "🇦🇩", 103 | flagURL: "unknwon", 104 | }; 105 | } 106 | } 107 | /** 108 | * Searching phone number on truecallerjs 109 | * @var response => {...} 110 | * @method response.json(color) JSON response. 111 | * @method response.xml(color) XML output. 112 | * @method response.yaml(color) YAML output. 113 | * @method response.html(color) HTML output. 114 | * @method response.text(color,space) JSON response. 115 | * @method response.getName() => "Sumith Emmadi" 116 | * @method response.getAlternateName() => "sumith" 117 | * @method response.getAddresses() => {....} 118 | * @method response.getEmailId() => sumithemmadi244@gmail.com 119 | * @method response.getCountryDetails() => {...} 120 | * @name search 121 | * @function truecallerjs.search(search_data) 122 | * @return {Object} It contains details of the phone number 123 | */ 124 | function search(searchData) { 125 | var _a; 126 | const phoneNumber = (0, awesome_phonenumber_1.parsePhoneNumber)(searchData.number, { 127 | regionCode: searchData.countryCode, 128 | }); 129 | const significantNumber = (_a = phoneNumber === null || phoneNumber === void 0 ? void 0 : phoneNumber.number) === null || _a === void 0 ? void 0 : _a.significant; 130 | return axios_1.default 131 | .get(`https://search5-noneu.truecaller.com/v2/search`, { 132 | params: { 133 | q: significantNumber, 134 | countryCode: phoneNumber.regionCode, 135 | type: 4, 136 | locAddr: "", 137 | placement: "SEARCHRESULTS,HISTORY,DETAILS", 138 | encoding: "json", 139 | }, 140 | headers: { 141 | "content-type": "application/json; charset=UTF-8", 142 | "accept-encoding": "gzip", 143 | "user-agent": "Truecaller/11.75.5 (Android;10)", 144 | Authorization: `Bearer ${searchData.installationId}`, 145 | }, 146 | }) 147 | .then((response) => { 148 | // console.log(response); 149 | return new Format(response.data); 150 | }, 151 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 152 | (error) => { 153 | return new Format(error); 154 | }); 155 | } 156 | exports.search = search; 157 | /** 158 | * Bulk search on truecallerjs 159 | * @name bulkSearch 160 | * @function truecallerjs.bulkSearch(phoneNumbers,countryCode,installationId) 161 | * @param {String} phoneNumbers phone number separted with coma. 162 | * @param {String} installationId 6-digits OTP . 163 | * @return {Object} It contains phone numbers information in a array 164 | */ 165 | function bulkSearch(phoneNumbers, regionCode, installationId) { 166 | return axios_1.default 167 | .get(`https://search5-noneu.truecaller.com/v2/bulk`, { 168 | params: { 169 | q: phoneNumbers, 170 | countryCode: regionCode, 171 | type: 14, 172 | placement: "SEARCHRESULTS,HISTORY,DETAILS", 173 | encoding: "json", 174 | }, 175 | headers: { 176 | "content-type": "application/json; charset=UTF-8", 177 | "accept-encoding": "gzip", 178 | "user-agent": "Truecaller/11.75.5 (Android;10)", 179 | Authorization: `Bearer ${installationId}`, 180 | }, 181 | }) 182 | .then((response) => { 183 | return response.data; 184 | }, 185 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 186 | (error) => { 187 | return JSON.parse(JSON.stringify(error)); 188 | }); 189 | } 190 | exports.bulkSearch = bulkSearch; 191 | -------------------------------------------------------------------------------- /dist/cjs/verifyOtp.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Verifying mobile number with OTP 3 | * 4 | * @name truecallerjs.verifyOtp 5 | * @function verifyOtp 6 | * @param {string} phonenumber - Phone number in international format. 7 | * @param {Object} json_data - JSON response of the login(phonenumber) function. 8 | * @param {string} otp - 6-digit OTP. 9 | * @returns {Promise} - JSON output containing the installationId. 10 | * 11 | * Follow this documentation for more details: https://github.com/sumithemmadi/truecallerjs/tree/main/docs 12 | */ 13 | declare function verifyOtp(phonenumber: string, json_data: any, otp: string): Promise; 14 | export { verifyOtp }; 15 | -------------------------------------------------------------------------------- /dist/cjs/verifyOtp.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* eslint-disable @typescript-eslint/no-explicit-any */ 3 | // MIT License 4 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 5 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 6 | return new (P || (P = Promise))(function (resolve, reject) { 7 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 8 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 9 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 10 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 11 | }); 12 | }; 13 | var __importDefault = (this && this.__importDefault) || function (mod) { 14 | return (mod && mod.__esModule) ? mod : { "default": mod }; 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | exports.verifyOtp = void 0; 18 | // Copyright (c) 2021 Emmadi Sumith Kumar 19 | // Permission is hereby granted, free of charge, to any person obtaining a copy 20 | // of this software and associated documentation files (the "Software"), to deal 21 | // in the Software without restriction, including without limitation the rights 22 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | // copies of the Software, and to permit persons to whom the Software is 24 | // furnished to do so, subject to the following conditions: 25 | // The above copyright notice and this permission notice shall be included in all 26 | // copies or substantial portions of the Software. 27 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 30 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | // SOFTWARE. 34 | const awesome_phonenumber_1 = require("awesome-phonenumber"); 35 | const axios_1 = __importDefault(require("axios")); 36 | /** 37 | * Verifying mobile number with OTP 38 | * 39 | * @name truecallerjs.verifyOtp 40 | * @function verifyOtp 41 | * @param {string} phonenumber - Phone number in international format. 42 | * @param {Object} json_data - JSON response of the login(phonenumber) function. 43 | * @param {string} otp - 6-digit OTP. 44 | * @returns {Promise} - JSON output containing the installationId. 45 | * 46 | * Follow this documentation for more details: https://github.com/sumithemmadi/truecallerjs/tree/main/docs 47 | */ 48 | function verifyOtp(phonenumber, json_data, otp) { 49 | return __awaiter(this, void 0, void 0, function* () { 50 | const pn = (0, awesome_phonenumber_1.parsePhoneNumber)(phonenumber); 51 | if (!pn.valid) { 52 | throw new Error("Phone number should be in international format."); 53 | } 54 | const postData = { 55 | countryCode: pn.regionCode, 56 | dialingCode: pn.countryCode, 57 | phoneNumber: pn.number.significant, 58 | requestId: json_data.requestId, 59 | token: otp, 60 | }; 61 | const options = { 62 | method: "POST", 63 | headers: { 64 | "content-type": "application/json; charset=UTF-8", 65 | "accept-encoding": "gzip", 66 | "user-agent": "Truecaller/11.75.5 (Android;10)", 67 | clientsecret: "lvc22mp3l1sfv6ujg83rd17btt", 68 | }, 69 | url: "https://account-asia-south1.truecaller.com/v1/verifyOnboardingOtp", 70 | data: postData, 71 | }; 72 | const res = yield (0, axios_1.default)(options); 73 | return res.data; 74 | }); 75 | } 76 | exports.verifyOtp = verifyOtp; 77 | -------------------------------------------------------------------------------- /dist/cli.d.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | export {}; 3 | -------------------------------------------------------------------------------- /dist/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | // MIT License 4 | 5 | // Copyright (c) 2021 Emmadi Sumith Kumar 6 | 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | 14 | // The above copyright notice and this permission notice shall be included in all 15 | // copies or substantial portions of the Software. 16 | 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | // SOFTWARE. 24 | */ 25 | import yargs from "yargs"; 26 | import { hideBin } from "yargs/helpers"; 27 | import fs from "fs"; 28 | import chalk from "chalk"; 29 | import path from "path"; 30 | import inquirer from "inquirer"; 31 | import { parsePhoneNumber } from "awesome-phonenumber"; 32 | import os from "os"; 33 | import { login } from "./login.js"; 34 | import { verifyOtp } from "./verifyOtp.js"; 35 | import { search, bulkSearch } from "./search.js"; 36 | import colorizeJson from "json-colorizer"; 37 | const homePath = os.homedir(); 38 | const truecallerjsAuthDirPath = path.join(homePath, ".config", "truecallerjs"); 39 | const requestFilePath = path.join(truecallerjsAuthDirPath, "request.json"); 40 | const authKeyFilePath = path.join(truecallerjsAuthDirPath, "authkey.json"); 41 | const runCLI = async () => { 42 | const args = yargs(hideBin(process.argv)) 43 | .usage("Usage: \n$0 login (Login to truecaller).\n$0 -s [number] (command to search a number).") 44 | .option("search", { 45 | alias: "s", 46 | description: "To search caller name and related information of a number", 47 | }) 48 | .option("raw", { 49 | alias: "r", 50 | description: "Print's raw output", 51 | type: "boolean", 52 | }) 53 | .option("bulksearch", { 54 | alias: "bs", 55 | description: "Make a bulk number search", 56 | }) 57 | .option("name", { 58 | alias: "n", 59 | description: "Print's user name of phone number ", 60 | type: "boolean", 61 | }) 62 | .option("email", { 63 | alias: "e", 64 | description: "Print's email assigned to the phonenumber", 65 | type: "boolean", 66 | }) 67 | .option("json", { 68 | description: "print's output in json", 69 | type: "boolean", 70 | }) 71 | .option("xml", { 72 | description: "print's output in XML", 73 | type: "boolean", 74 | }) 75 | .option("yaml", { 76 | description: "Print's output in YAML", 77 | type: "boolean", 78 | }) 79 | .option("text", { 80 | description: "Print's output as plain text(TXT)", 81 | type: "boolean", 82 | }) 83 | .option("nc", { 84 | alias: "no_color", 85 | description: "Print without color", 86 | type: "boolean", 87 | }) 88 | .option("installationid", { 89 | alias: "i", 90 | description: "shows your InstallationId", 91 | type: "boolean", 92 | }) 93 | .option("verbose", { 94 | alias: "v", 95 | description: "Show additional information", 96 | type: "count", 97 | }) 98 | .help() 99 | .alias("help", "h") 100 | .parseSync(); 101 | if (args._.includes("login") && !args.s && !args.bs) { 102 | // Create the auth directory for truecallerjs if it doesn't exist 103 | if (!fs.existsSync(truecallerjsAuthDirPath)) { 104 | try { 105 | fs.mkdirSync(truecallerjsAuthDirPath, { recursive: true }); 106 | } 107 | catch (error) { 108 | console.log(error); 109 | process.exit(1); 110 | } 111 | } 112 | // Starts here 113 | if (args._[0] === "login" && args._.length <= 2) { 114 | console.log(chalk.yellow.bold("Login\n\n Enter mobile number in International Format\n Example : ") + 115 | chalk.magenta("+919912345678") + 116 | ".\n"); 117 | const inputNumber = await inquirer.prompt({ 118 | type: "input", 119 | name: "phonenumber", 120 | message: "Enter your phone number :", 121 | validate: async (input) => { 122 | const check = parsePhoneNumber(input); 123 | if (input !== (check?.number?.e164 ?? "")) { 124 | return "Enter a valid phone number in International Format"; 125 | } 126 | if (!check?.valid) { 127 | return "Invalid Phone Number"; 128 | } 129 | return true; 130 | }, 131 | }); 132 | const pn = parsePhoneNumber(inputNumber.phonenumber); 133 | let response; 134 | let new_req = true; 135 | if (fs.existsSync(requestFilePath)) { 136 | const fileData = JSON.parse(fs.readFileSync(requestFilePath, "utf8")); 137 | if ("parsedPhoneNumber" in fileData && 138 | `+${fileData.parsedPhoneNumber}` == pn?.number?.e164) { 139 | console.log(chalk.magenta("\nPrevious request was found for this mobile number.\n")); 140 | const x = await inquirer.prompt({ 141 | type: "confirm", 142 | name: "status", 143 | message: "Do you want to enter previous OTP ", 144 | }); 145 | if (x.status) { 146 | new_req = false; 147 | response = fileData; 148 | } 149 | } 150 | } 151 | if (new_req) { 152 | response = await login(String(pn?.number?.e164)); 153 | console.log(chalk.yellow(`Sending OTP to ${chalk.green(pn?.number?.e164 ?? "")}.`)); 154 | } 155 | if (response.status == 1 || 156 | response.status == 9 || 157 | response.message == "Sent") { 158 | // Otp sent 159 | try { 160 | fs.writeFileSync(requestFilePath, JSON.stringify(response, null, 4)); 161 | if (new_req) { 162 | console.log(chalk.green("OTP sent successfully.")); 163 | } 164 | const token = await inquirer.prompt({ 165 | type: "input", 166 | name: "otp", 167 | message: "Enter Received OTP:", 168 | validate: async (input) => { 169 | const isnum = /^\d+$/.test(String(input)); 170 | if (input.length !== 6 || !isnum) { 171 | return "Enter a valid 6-digit OTP."; 172 | } 173 | return true; 174 | }, 175 | }); 176 | const response1 = await verifyOtp(String(pn?.number?.e164), response, token.otp); 177 | if (response1.status === 2 && !response1.suspended) { 178 | console.log(chalk.yellow.bold("Your installationId: ") + 179 | chalk.green(response1.installationId)); 180 | console.log(`This is the installationId: ${chalk.green(response1.installationId)} used to authenticate with Truecaller.`); 181 | // Save the file 182 | fs.writeFileSync(authKeyFilePath, JSON.stringify(response1, null, 3)); 183 | console.log(chalk.green("Logged in successfully.")); 184 | fs.unlinkSync(requestFilePath); 185 | } 186 | else if (response1.status === 11) { 187 | console.log(chalk.red("! Invalid OTP")); 188 | console.log(`OTP not valid. Enter the 6-digit OTP received on ${pn?.number?.e164}.`); 189 | } 190 | else if (response1.status === 7) { 191 | console.log(chalk.red("Retries limit exceeded")); 192 | console.log(`Retries on secret code reached for ${pn?.number?.e164}.`); 193 | } 194 | else if (response1.suspended) { 195 | console.log(chalk.red("Oops... Your account is suspended.")); 196 | console.log("Your account has been suspended by Truecaller."); 197 | } 198 | else if ("message" in response1) { 199 | console.log(chalk.red(response1.message)); 200 | } 201 | else { 202 | console.log(JSON.stringify(response1, null, 4)); 203 | } 204 | } 205 | catch (error) { 206 | if (error instanceof Error) { 207 | console.log(chalk.red(error.message)); 208 | } 209 | else { 210 | console.log(chalk.red("An error occurred.")); 211 | } 212 | process.exit(1); 213 | } 214 | } 215 | else if (response.status == 6 || response.status == 5) { 216 | if (fs.existsSync(requestFilePath)) { 217 | fs.unlinkSync(requestFilePath); 218 | } 219 | console.log(chalk.red("You have exceeded the limit of verification attempts.\nPlease try again after some time.")); 220 | } 221 | else { 222 | console.log(chalk.red(response.message)); 223 | } 224 | } 225 | } 226 | else if (args.s && !args.bs && !args._.includes("login") && !args.i) { 227 | if (!fs.existsSync(authKeyFilePath)) { 228 | console.error(chalk.magenta.bold("Please login to your account.")); 229 | process.exit(); 230 | } 231 | try { 232 | const data = fs.readFileSync(authKeyFilePath, "utf8"); 233 | const jsonAuthKey = JSON.parse(data); 234 | const countryCode = jsonAuthKey.phones[0].countryCode; 235 | const installationId = jsonAuthKey.installationId; 236 | const search_result = await search({ 237 | number: String(args.s), 238 | countryCode, 239 | installationId, 240 | }); 241 | if (args.json || args.xml || args.text || args.yaml) { 242 | if (args.json && !args.xml && !args.text && !args.yaml) { 243 | if (args.r) { 244 | console.log(!args.nc 245 | ? colorizeJson(JSON.stringify(search_result.json()), { 246 | colors: { 247 | STRING_KEY: "blue", 248 | STRING_LITERAL: "green", 249 | NUMBER_LITERAL: "magenta", 250 | }, 251 | }) 252 | : JSON.stringify(search_result.json())); 253 | } 254 | else { 255 | console.log(!args.nc 256 | ? colorizeJson(JSON.stringify(search_result.json()), { 257 | pretty: true, 258 | colors: { 259 | STRING_KEY: "blue", 260 | STRING_LITERAL: "green", 261 | NUMBER_LITERAL: "magenta", 262 | }, 263 | }) 264 | : JSON.stringify(search_result.json(), null, 2)); 265 | } 266 | } 267 | else if (args.xml && !args.json && !args.text && !args.yaml) { 268 | console.log(search_result.xml(!args.nc)); 269 | } 270 | else if (args.yaml && !args.xml && !args.text && !args.json) { 271 | console.log(search_result.yaml(!args.nc)); 272 | } 273 | else { 274 | console.log(search_result.text(!args.nc, true)); 275 | } 276 | } 277 | else { 278 | if (args.n && !args.r && !args.e) { 279 | console.log(chalk.blue.bold("Name"), " : ", chalk.green(search_result.getName())); 280 | } 281 | else if (args.n && args.r && !args.e) { 282 | console.log(search_result.getName()); 283 | } 284 | else if (!args.n && !args.r && args.e) { 285 | console.log(chalk.blue.bold("Email"), " : ", chalk.green(search_result.getEmailId())); 286 | } 287 | else if (!args.n && args.r && args.e) { 288 | console.log(search_result.getEmailId()); 289 | } 290 | else { 291 | console.log(search_result.text(!args.nc, true)); 292 | } 293 | } 294 | } 295 | catch (error) { 296 | if (error instanceof Error) { 297 | console.log(chalk.red(error.message)); 298 | } 299 | else { 300 | console.log(chalk.red("An error occurred.")); 301 | } 302 | process.exit(1); 303 | } 304 | } 305 | else if (args.bs && !args._.includes("login") && !args.i) { 306 | if (!fs.existsSync(authKeyFilePath)) { 307 | console.error(chalk.magenta.bold("Please login to your account.")); 308 | process.exit(1); 309 | } 310 | try { 311 | const data = fs.readFileSync(authKeyFilePath, "utf8"); 312 | const jsonAuthKey = JSON.parse(data); 313 | const countryCode = jsonAuthKey.phones[0].countryCode; 314 | const installationId = jsonAuthKey.installationId; 315 | const searchResult = await bulkSearch(String(args?.bs), countryCode, installationId); 316 | if (args.r) { 317 | console.log(!args.nc 318 | ? colorizeJson(JSON.stringify(searchResult), { 319 | colors: { 320 | STRING_KEY: "blue", 321 | STRING_LITERAL: "green", 322 | NUMBER_LITERAL: "magenta", 323 | }, 324 | }) 325 | : JSON.stringify(searchResult)); 326 | } 327 | else { 328 | console.log(!args.nc 329 | ? colorizeJson(JSON.stringify(searchResult), { 330 | pretty: true, 331 | colors: { 332 | STRING_KEY: "blue", 333 | STRING_LITERAL: "green", 334 | NUMBER_LITERAL: "magenta", 335 | }, 336 | }) 337 | : JSON.stringify(searchResult, null, 2)); 338 | } 339 | } 340 | catch (error) { 341 | if (error instanceof Error) { 342 | console.log(chalk.red(error.message)); 343 | } 344 | else { 345 | console.log(chalk.red("An error occurred.")); 346 | } 347 | process.exit(1); 348 | } 349 | } 350 | else if (args.i && !args.s) { 351 | if (!fs.existsSync(authKeyFilePath)) { 352 | console.error(chalk.magenta.bold("Please login to your account.")); 353 | process.exit(1); 354 | } 355 | try { 356 | const data = fs.readFileSync(authKeyFilePath, "utf8"); 357 | const jsonAuthKey = JSON.parse(data); 358 | // let countryCode = jsonAuthKey.phones[0].countryCode; 359 | const installationId = jsonAuthKey.installationId; 360 | if (args.r) { 361 | console.log(installationId); 362 | } 363 | else { 364 | args.nc 365 | ? console.log("Your InstallationId : " + installationId) 366 | : console.log(chalk.blue.bold("Your InstallationId") + 367 | " : " + 368 | chalk.green(installationId)); 369 | } 370 | } 371 | catch (error) { 372 | if (error instanceof Error) { 373 | console.log(chalk.red(error.message)); 374 | } 375 | else { 376 | console.log(chalk.red("An error occurred.")); 377 | } 378 | process.exit(1); 379 | } 380 | } 381 | else { 382 | console.log(`Usage: 383 | ${chalk.green("truecallerjs")} login (Login to truecaller). 384 | ${chalk.green("truecallerjs")} -s [number] (command to search a number). 385 | 386 | Options: 387 | --version Show version number [boolean] 388 | -s, --search To search caller name and related information of a num 389 | ber 390 | -r, --raw Print's raw output [boolean] 391 | --bulksearch, --bs Make a bulk number search 392 | -n, --name Print's user name of phone number [boolean] 393 | -e, --email Print's email assigned to the phonenumber [boolean] 394 | --json print's output in json [boolean] 395 | --xml print's output in XML [boolean] 396 | --yaml Print's output in YAML [boolean] 397 | --text Print's output as plain text(TXT) [boolean] 398 | --nc, --no_color Print without color [boolean] 399 | -i, --installationid shows your InstallationId [boolean] 400 | -v, --verbose Show additional information [count] 401 | -h, --help Show help [boolean] 402 | 403 | Repository => https://github.com/sumithemmadi/truecallerjs 404 | `); 405 | } 406 | }; 407 | runCLI(); 408 | -------------------------------------------------------------------------------- /dist/data/countries.d.ts: -------------------------------------------------------------------------------- 1 | interface CountryData { 2 | name: string; 3 | native: string; 4 | phone: number[]; 5 | continent: string; 6 | capital: string; 7 | currency: string[]; 8 | languages: string[]; 9 | flag: string; 10 | flagURL: string; 11 | } 12 | interface Countries { 13 | [countryCode: string]: CountryData; 14 | } 15 | declare const countries: Countries; 16 | export { countries }; 17 | -------------------------------------------------------------------------------- /dist/data/phones.d.ts: -------------------------------------------------------------------------------- 1 | declare const device: { 2 | manufacturer: string; 3 | model: string; 4 | }; 5 | export { device }; 6 | -------------------------------------------------------------------------------- /dist/data/phones.js: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright (c) 2021 Emmadi Sumith Kumar 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // The above copyright notice and this permission notice shall be included in all 10 | // copies or substantial portions of the Software. 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | // SOFTWARE. 18 | const phones_list = [ 19 | { 20 | manufacturer: "Xiaomi", 21 | model: "M2010J19SG", 22 | }, 23 | { 24 | manufacturer: "Xiaomi", 25 | model: "POCO F1", 26 | }, 27 | { 28 | manufacturer: "Xiaomi", 29 | model: "Redmi 9A", 30 | }, 31 | { 32 | manufacturer: "Xiaomi", 33 | model: "Xiaomi Mi 4", 34 | }, 35 | { 36 | manufacturer: "Xiaomi", 37 | model: "Redmi Note 10 pro", 38 | }, 39 | { 40 | manufacturer: "Xiaomi", 41 | model: "Redmi Note 10", 42 | }, 43 | { 44 | manufacturer: "Xiaomi", 45 | model: "Xiaomi Redmi 1S", 46 | }, 47 | { 48 | manufacturer: "Xiaomi", 49 | model: "Xiaomi Mi 10T", 50 | }, 51 | { 52 | manufacturer: "Xiaomi", 53 | model: "Xiaomi Redmi 6 Pro", 54 | }, 55 | { 56 | manufacturer: "Xiaomi", 57 | model: "Xiaomi Redmi Y3", 58 | }, 59 | { 60 | manufacturer: "Xiaomi", 61 | model: "Xiaomi Redmi 9 Prime", 62 | }, 63 | { 64 | manufacturer: "Xiaomi", 65 | model: "Redmi Note 7", 66 | }, 67 | { 68 | manufacturer: "Vivo", 69 | model: "Vivo Y33s", 70 | }, 71 | { 72 | manufacturer: "Vivo", 73 | model: "Vivo V21 5G", 74 | }, 75 | { 76 | manufacturer: "Vivo", 77 | model: "Vivo Y20T", 78 | }, 79 | { 80 | manufacturer: "Vivo", 81 | model: "Vivo Y73 2021", 82 | }, 83 | { 84 | manufacturer: "Vivo", 85 | model: "Vivo X60", 86 | }, 87 | { 88 | manufacturer: "Vivo", 89 | model: "Vivo X70 Pro 5G", 90 | }, 91 | { 92 | manufacturer: "Vivo", 93 | model: "Vivo U3x", 94 | }, 95 | { 96 | manufacturer: "Vivo", 97 | model: "Vivo V20 Pro", 98 | }, 99 | { 100 | manufacturer: "Vivo", 101 | model: "Vivo Y21 2021", 102 | }, 103 | { 104 | manufacturer: "Vivo", 105 | model: "Vivo Y53s", 106 | }, 107 | { 108 | manufacturer: "Vivo", 109 | model: "Vivo S12 Pro", 110 | }, 111 | { 112 | manufacturer: "Vivo", 113 | model: "Vivo V21e 5G", 114 | }, 115 | { 116 | manufacturer: "OnePlus", 117 | model: "OnePlus Nord CE 5G", 118 | }, 119 | { 120 | manufacturer: "OnePlus", 121 | model: "OnePlus 9 Pro", 122 | }, 123 | { 124 | manufacturer: "OnePlus", 125 | model: "OnePlus 8T", 126 | }, 127 | { 128 | manufacturer: "OnePlus", 129 | model: "OnePlus 9", 130 | }, 131 | { 132 | manufacturer: "OnePlus", 133 | model: "OnePlus 7T", 134 | }, 135 | { 136 | manufacturer: "OnePlus", 137 | model: "OnePlus 6T", 138 | }, 139 | { 140 | manufacturer: "OnePlus", 141 | model: "OnePlus Nord 2", 142 | }, 143 | { 144 | manufacturer: "OnePlus", 145 | model: "OnePlus 7 Pro", 146 | }, 147 | { 148 | manufacturer: "OnePlus", 149 | model: "OnePlus Nord", 150 | }, 151 | { 152 | manufacturer: "Realme", 153 | model: "RMX2185", 154 | }, 155 | { 156 | manufacturer: "Realme", 157 | model: "Realme GT Neo2 5G", 158 | }, 159 | { 160 | manufacturer: "Realme", 161 | model: "Realme 8 5G", 162 | }, 163 | { 164 | manufacturer: "Realme", 165 | model: "Realme C11 2021", 166 | }, 167 | { 168 | manufacturer: "Realme", 169 | model: "Realme GT", 170 | }, 171 | { 172 | manufacturer: "Realme", 173 | model: "Realme Narzo 30", 174 | }, 175 | { 176 | manufacturer: "Realme", 177 | model: "Realme Q3i 5G", 178 | }, 179 | { 180 | manufacturer: "Realme", 181 | model: "Realme 8s 5G", 182 | }, 183 | { 184 | manufacturer: "Realme", 185 | model: "Realme 8i", 186 | }, 187 | { 188 | manufacturer: "Realme", 189 | model: "Realme Narzo 50A", 190 | }, 191 | { 192 | manufacturer: "Realme", 193 | model: "Realme C21Y", 194 | }, 195 | { 196 | manufacturer: "Oppo", 197 | model: "OPPO A55", 198 | }, 199 | { 200 | manufacturer: "Oppo", 201 | model: "OPPO A74 5G", 202 | }, 203 | { 204 | manufacturer: "Oppo", 205 | model: "OPPO A53", 206 | }, 207 | { 208 | manufacturer: "Oppo", 209 | model: "OPPO A31", 210 | }, 211 | { 212 | manufacturer: "Oppo", 213 | model: "OPPO A12", 214 | }, 215 | { 216 | manufacturer: "Oppo", 217 | model: "OPPO Reno6 Pro", 218 | }, 219 | { 220 | manufacturer: "Oppo", 221 | model: "OPPO Reno6", 222 | }, 223 | { 224 | manufacturer: "Oppo", 225 | model: "OPPO F19 Pro", 226 | }, 227 | { 228 | manufacturer: "Oppo", 229 | model: "OPPO F19s", 230 | }, 231 | { 232 | manufacturer: "Oppo", 233 | model: "Oppo F19 Pro+", 234 | }, 235 | { 236 | manufacturer: "Oppo", 237 | model: "Oppo A33", 238 | }, 239 | { 240 | manufacturer: "Oppo", 241 | model: "Oppo Reno 3 Pro", 242 | }, 243 | { 244 | manufacturer: "Oppo", 245 | model: "Oppo Reno 4 Pro", 246 | }, 247 | { 248 | manufacturer: "Oppo", 249 | model: "Oppo Find X2", 250 | }, 251 | { 252 | manufacturer: "Oppo", 253 | model: "OPPO F15", 254 | }, 255 | { 256 | manufacturer: "Oppo", 257 | model: "OPPO Reno 2F", 258 | }, 259 | { 260 | manufacturer: "Oppo", 261 | model: "OPPO K3", 262 | }, 263 | { 264 | manufacturer: "Oppo", 265 | model: "OPPO A9", 266 | }, 267 | { 268 | manufacturer: "Oppo", 269 | model: "OPPO A1k", 270 | }, 271 | { 272 | manufacturer: "Oppo", 273 | model: "OPPO A5s", 274 | }, 275 | { 276 | manufacturer: "Samsung", 277 | model: "Samsung Galaxy M31s", 278 | }, 279 | { 280 | manufacturer: "Samsung", 281 | model: "Samsung Galaxy M32", 282 | }, 283 | { 284 | manufacturer: "Samsung", 285 | model: "Samsung Galaxy F62", 286 | }, 287 | { 288 | manufacturer: "Samsung", 289 | model: "Samsung Galaxy M52 5G", 290 | }, 291 | { 292 | manufacturer: "Samsung", 293 | model: "Samsung Galaxy M12", 294 | }, 295 | { 296 | manufacturer: "Samsung", 297 | model: "Samsung Galaxy M51", 298 | }, 299 | { 300 | manufacturer: "Samsung", 301 | model: "Samsung Galaxy F12", 302 | }, 303 | { 304 | manufacturer: "Samsung", 305 | model: "Samsung Galaxy F22", 306 | }, 307 | { 308 | manufacturer: "Samsung", 309 | model: "Samsung Galaxy A52", 310 | }, 311 | { 312 | manufacturer: "Samsung", 313 | model: "Samsung Galaxy S20 FE 5G", 314 | }, 315 | { 316 | manufacturer: "Samsung", 317 | model: "Samsung Galaxy M52", 318 | }, 319 | { 320 | manufacturer: "Samsung", 321 | model: "Samsung Galaxy M62", 322 | }, 323 | { 324 | manufacturer: "Samsung", 325 | model: "Samsung Galaxy S21 Ultra", 326 | }, 327 | { 328 | manufacturer: "Samsung", 329 | model: "Samsung Galaxy A52s 5G", 330 | }, 331 | { 332 | manufacturer: "Samsung", 333 | model: "Samsung Galaxy S21", 334 | }, 335 | { 336 | manufacturer: "Samsung", 337 | model: "Samsung Galaxy M21 2021", 338 | }, 339 | { 340 | manufacturer: "Samsung", 341 | model: "Samsung Galaxy F42", 342 | }, 343 | { 344 | manufacturer: "Samsung", 345 | model: "Samsung Galaxy A12", 346 | }, 347 | { 348 | manufacturer: "Samsung", 349 | model: "Samsung Galaxy F41", 350 | }, 351 | { 352 | manufacturer: "Samsung", 353 | model: "Samsung Galaxy M01 Core", 354 | }, 355 | ]; 356 | const getRandomDevice = () => { 357 | const randomIndex = Math.floor(Math.random() * phones_list.length); 358 | return phones_list[randomIndex]; 359 | }; 360 | const device = getRandomDevice(); 361 | export { device }; 362 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import { login as loginFunction } from "./login.js"; 2 | import { verifyOtp as verifyOtpFunction } from "./verifyOtp.js"; 3 | import { search as searchFunction, bulkSearch as bulkSearchFunction } from "./search.js"; 4 | export declare const login: typeof loginFunction; 5 | export declare const verifyOtp: typeof verifyOtpFunction; 6 | export declare const search: typeof searchFunction; 7 | export declare const bulkSearch: typeof bulkSearchFunction; 8 | declare const truecallerjs: { 9 | login: typeof loginFunction; 10 | verifyOtp: typeof verifyOtpFunction; 11 | search: typeof searchFunction; 12 | bulkSearch: typeof bulkSearchFunction; 13 | }; 14 | export default truecallerjs; 15 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright (c) 2021 Emmadi Sumith Kumar 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // The above copyright notice and this permission notice shall be included in all 10 | // copies or substantial portions of the Software. 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | // SOFTWARE. 18 | import { login as loginFunction } from "./login.js"; 19 | import { verifyOtp as verifyOtpFunction } from "./verifyOtp.js"; 20 | import { search as searchFunction, bulkSearch as bulkSearchFunction, } from "./search.js"; 21 | export const login = loginFunction; 22 | export const verifyOtp = verifyOtpFunction; 23 | export const search = searchFunction; 24 | export const bulkSearch = bulkSearchFunction; 25 | const truecallerjs = { 26 | login, 27 | verifyOtp, 28 | search, 29 | bulkSearch, 30 | }; 31 | export default truecallerjs; 32 | -------------------------------------------------------------------------------- /dist/login.d.ts: -------------------------------------------------------------------------------- 1 | interface LoginResponse { 2 | status: number; 3 | message: string; 4 | domain: string; 5 | parsedPhoneNumber: number; 6 | parsedCountryCode: string; 7 | requestId: string; 8 | method: string; 9 | tokenTtl: number; 10 | } 11 | /** 12 | * Login to Truecaller. 13 | * 14 | * @param {string} phoneNumber - Phone number in international format. 15 | * @returns {Promise} - Promise that resolves to the login response containing the requestId used for OTP verification. 16 | */ 17 | declare function login(phoneNumber: string): Promise; 18 | export { login }; 19 | -------------------------------------------------------------------------------- /dist/login.js: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright (c) 2021 Emmadi Sumith Kumar 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // The above copyright notice and this permission notice shall be included in all 10 | // copies or substantial portions of the Software. 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | // SOFTWARE. 18 | import axios from "axios"; 19 | import { parsePhoneNumber } from "awesome-phonenumber"; 20 | import { device } from "./data/phones.js"; 21 | function generateRandomString(length) { 22 | let result = ""; 23 | const characters = "abcdefghijklmnopqrstuvwxyz0123456789"; 24 | const charactersLength = characters.length; 25 | for (let i = 0; i < length; i++) { 26 | result += characters.charAt(Math.floor(Math.random() * charactersLength)); 27 | } 28 | return result; 29 | } 30 | /** 31 | * Login to Truecaller. 32 | * 33 | * @param {string} phoneNumber - Phone number in international format. 34 | * @returns {Promise} - Promise that resolves to the login response containing the requestId used for OTP verification. 35 | */ 36 | async function login(phoneNumber) { 37 | const pn = parsePhoneNumber(phoneNumber); 38 | if (!pn?.valid) { 39 | throw new Error("Invalid phone number."); 40 | } 41 | const postUrl = "https://account-asia-south1.truecaller.com/v2/sendOnboardingOtp"; 42 | const data = { 43 | countryCode: pn.regionCode, 44 | dialingCode: pn.countryCode, 45 | installationDetails: { 46 | app: { 47 | buildVersion: 5, 48 | majorVersion: 11, 49 | minorVersion: 7, 50 | store: "GOOGLE_PLAY", 51 | }, 52 | device: { 53 | deviceId: generateRandomString(16), 54 | language: "en", 55 | manufacturer: device.manufacturer, 56 | model: device.model, 57 | osName: "Android", 58 | osVersion: "10", 59 | mobileServices: ["GMS"], 60 | }, 61 | language: "en", 62 | }, 63 | phoneNumber: pn.number.significant, 64 | region: "region-2", 65 | sequenceNo: 2, 66 | }; 67 | const options = { 68 | method: "POST", 69 | headers: { 70 | "content-type": "application/json; charset=UTF-8", 71 | "accept-encoding": "gzip", 72 | "user-agent": "Truecaller/11.75.5 (Android;10)", 73 | clientsecret: "lvc22mp3l1sfv6ujg83rd17btt", 74 | }, 75 | url: postUrl, 76 | data, 77 | }; 78 | const res = await axios(options); 79 | return res.data; 80 | } 81 | export { login }; 82 | -------------------------------------------------------------------------------- /dist/search.d.ts: -------------------------------------------------------------------------------- 1 | interface Address { 2 | city: string; 3 | countryCode: string; 4 | timeZone: string; 5 | type: string; 6 | } 7 | interface InternetAddress { 8 | id: string; 9 | service: string; 10 | caption: string; 11 | type: string; 12 | } 13 | interface CountryDetails { 14 | name: string; 15 | native: string; 16 | phone: number[]; 17 | continent: string; 18 | capital: string; 19 | currency: string[]; 20 | languages: string[]; 21 | flag: string; 22 | flagURL: string; 23 | } 24 | interface Data { 25 | name?: string; 26 | altName?: string; 27 | addresses?: Address[]; 28 | internetAddresses?: InternetAddress[]; 29 | } 30 | interface SearchData { 31 | number: string; 32 | countryCode: string; 33 | installationId: string; 34 | } 35 | interface BulkSearchData { 36 | data: Data[]; 37 | } 38 | declare class Format { 39 | private data; 40 | constructor(data: BulkSearchData); 41 | json(): BulkSearchData; 42 | xml(color?: boolean): string; 43 | yaml(color?: boolean): string; 44 | text(color?: boolean, space?: boolean): string; 45 | getName(): string; 46 | getAlternateName(): string; 47 | getAddresses(): Address[]; 48 | getEmailId(): string; 49 | getCountryDetails(): CountryDetails; 50 | } 51 | /** 52 | * Searching phone number on truecallerjs 53 | * @var response => {...} 54 | * @method response.json(color) JSON response. 55 | * @method response.xml(color) XML output. 56 | * @method response.yaml(color) YAML output. 57 | * @method response.html(color) HTML output. 58 | * @method response.text(color,space) JSON response. 59 | * @method response.getName() => "Sumith Emmadi" 60 | * @method response.getAlternateName() => "sumith" 61 | * @method response.getAddresses() => {....} 62 | * @method response.getEmailId() => sumithemmadi244@gmail.com 63 | * @method response.getCountryDetails() => {...} 64 | * @name search 65 | * @function truecallerjs.search(search_data) 66 | * @return {Object} It contains details of the phone number 67 | */ 68 | declare function search(searchData: SearchData): Promise; 69 | /** 70 | * Bulk search on truecallerjs 71 | * @name bulkSearch 72 | * @function truecallerjs.bulkSearch(phoneNumbers,countryCode,installationId) 73 | * @param {String} phoneNumbers phone number separted with coma. 74 | * @param {String} installationId 6-digits OTP . 75 | * @return {Object} It contains phone numbers information in a array 76 | */ 77 | declare function bulkSearch(phoneNumbers: string, regionCode: string, installationId: string): Promise; 78 | export { search, bulkSearch }; 79 | -------------------------------------------------------------------------------- /dist/search.js: -------------------------------------------------------------------------------- 1 | // MIT License 2 | // Copyright (c) 2021 Emmadi Sumith Kumar 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // The above copyright notice and this permission notice shall be included in all 10 | // copies or substantial portions of the Software. 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | // SOFTWARE. 18 | import axios from "axios"; 19 | import { parsePhoneNumber } from "awesome-phonenumber"; 20 | import { Builder } from "xml2js"; 21 | import { jsonToPlainText } from "json-to-plain-text"; 22 | import { stringify as yamlStringify } from "json-to-pretty-yaml"; 23 | import { countries } from "./data/countries.js"; 24 | class Format { 25 | data; 26 | constructor(data) { 27 | this.data = data; 28 | } 29 | json() { 30 | return this.data; 31 | } 32 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 33 | xml(color = false) { 34 | const builder = new Builder(); 35 | const xml = builder.buildObject(JSON.parse(JSON.stringify(this.json()))); 36 | return xml; 37 | } 38 | yaml(color = false) { 39 | return yamlStringify(JSON.parse(JSON.stringify(this.json())), color); 40 | } 41 | text(color = false, space = false) { 42 | const options = { 43 | color: color, 44 | spacing: space, 45 | squareBracketsForArray: false, 46 | doubleQuotesForKeys: false, 47 | doubleQuotesForValues: false, 48 | }; 49 | return jsonToPlainText(JSON.parse(JSON.stringify(this.json())), options); 50 | } 51 | getName() { 52 | return this.json()?.data[0]?.name || "unknown name"; 53 | } 54 | getAlternateName() { 55 | return this.json()?.data[0]?.altName || "no alternate name"; 56 | } 57 | getAddresses() { 58 | return this.json()?.data[0]?.addresses || []; 59 | } 60 | getEmailId() { 61 | const data = this.json()?.data; 62 | if (data && data.length > 0) { 63 | const internetAddresses = data[0]?.internetAddresses; 64 | if (internetAddresses && internetAddresses.length > 0) { 65 | const id = internetAddresses[0]?.id; 66 | if (id) { 67 | return id; 68 | } 69 | } 70 | } 71 | return "unknown email"; 72 | } 73 | getCountryDetails() { 74 | const data = this.json()?.data; 75 | if (data && data.length > 0) { 76 | const addresses = data[0]?.addresses; 77 | if (addresses && addresses.length > 0) { 78 | const countryCode = addresses[0]?.countryCode; 79 | if (countryCode) { 80 | return countries[countryCode]; 81 | } 82 | } 83 | } 84 | return { 85 | name: "unknown", 86 | native: "unknwon", 87 | phone: [], 88 | continent: "unknwon", 89 | capital: "unknwon", 90 | currency: ["unknwon"], 91 | languages: ["unknwon"], 92 | flag: "🇦🇩", 93 | flagURL: "unknwon", 94 | }; 95 | } 96 | } 97 | /** 98 | * Searching phone number on truecallerjs 99 | * @var response => {...} 100 | * @method response.json(color) JSON response. 101 | * @method response.xml(color) XML output. 102 | * @method response.yaml(color) YAML output. 103 | * @method response.html(color) HTML output. 104 | * @method response.text(color,space) JSON response. 105 | * @method response.getName() => "Sumith Emmadi" 106 | * @method response.getAlternateName() => "sumith" 107 | * @method response.getAddresses() => {....} 108 | * @method response.getEmailId() => sumithemmadi244@gmail.com 109 | * @method response.getCountryDetails() => {...} 110 | * @name search 111 | * @function truecallerjs.search(search_data) 112 | * @return {Object} It contains details of the phone number 113 | */ 114 | function search(searchData) { 115 | const phoneNumber = parsePhoneNumber(searchData.number, { 116 | regionCode: searchData.countryCode, 117 | }); 118 | const significantNumber = phoneNumber?.number?.significant; 119 | return axios 120 | .get(`https://search5-noneu.truecaller.com/v2/search`, { 121 | params: { 122 | q: significantNumber, 123 | countryCode: phoneNumber.regionCode, 124 | type: 4, 125 | locAddr: "", 126 | placement: "SEARCHRESULTS,HISTORY,DETAILS", 127 | encoding: "json", 128 | }, 129 | headers: { 130 | "content-type": "application/json; charset=UTF-8", 131 | "accept-encoding": "gzip", 132 | "user-agent": "Truecaller/11.75.5 (Android;10)", 133 | Authorization: `Bearer ${searchData.installationId}`, 134 | }, 135 | }) 136 | .then((response) => { 137 | // console.log(response); 138 | return new Format(response.data); 139 | }, 140 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 141 | (error) => { 142 | return new Format(error); 143 | }); 144 | } 145 | /** 146 | * Bulk search on truecallerjs 147 | * @name bulkSearch 148 | * @function truecallerjs.bulkSearch(phoneNumbers,countryCode,installationId) 149 | * @param {String} phoneNumbers phone number separted with coma. 150 | * @param {String} installationId 6-digits OTP . 151 | * @return {Object} It contains phone numbers information in a array 152 | */ 153 | function bulkSearch(phoneNumbers, regionCode, installationId) { 154 | return axios 155 | .get(`https://search5-noneu.truecaller.com/v2/bulk`, { 156 | params: { 157 | q: phoneNumbers, 158 | countryCode: regionCode, 159 | type: 14, 160 | placement: "SEARCHRESULTS,HISTORY,DETAILS", 161 | encoding: "json", 162 | }, 163 | headers: { 164 | "content-type": "application/json; charset=UTF-8", 165 | "accept-encoding": "gzip", 166 | "user-agent": "Truecaller/11.75.5 (Android;10)", 167 | Authorization: `Bearer ${installationId}`, 168 | }, 169 | }) 170 | .then((response) => { 171 | return response.data; 172 | }, 173 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 174 | (error) => { 175 | return JSON.parse(JSON.stringify(error)); 176 | }); 177 | } 178 | export { search, bulkSearch }; 179 | -------------------------------------------------------------------------------- /dist/verifyOtp.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Verifying mobile number with OTP 3 | * 4 | * @name truecallerjs.verifyOtp 5 | * @function verifyOtp 6 | * @param {string} phonenumber - Phone number in international format. 7 | * @param {Object} json_data - JSON response of the login(phonenumber) function. 8 | * @param {string} otp - 6-digit OTP. 9 | * @returns {Promise} - JSON output containing the installationId. 10 | * 11 | * Follow this documentation for more details: https://github.com/sumithemmadi/truecallerjs/tree/main/docs 12 | */ 13 | declare function verifyOtp(phonenumber: string, json_data: any, otp: string): Promise; 14 | export { verifyOtp }; 15 | -------------------------------------------------------------------------------- /dist/verifyOtp.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | // MIT License 3 | // Copyright (c) 2021 Emmadi Sumith Kumar 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 18 | // SOFTWARE. 19 | import { parsePhoneNumber } from "awesome-phonenumber"; 20 | import axios from "axios"; 21 | /** 22 | * Verifying mobile number with OTP 23 | * 24 | * @name truecallerjs.verifyOtp 25 | * @function verifyOtp 26 | * @param {string} phonenumber - Phone number in international format. 27 | * @param {Object} json_data - JSON response of the login(phonenumber) function. 28 | * @param {string} otp - 6-digit OTP. 29 | * @returns {Promise} - JSON output containing the installationId. 30 | * 31 | * Follow this documentation for more details: https://github.com/sumithemmadi/truecallerjs/tree/main/docs 32 | */ 33 | async function verifyOtp(phonenumber, json_data, otp) { 34 | const pn = parsePhoneNumber(phonenumber); 35 | if (!pn.valid) { 36 | throw new Error("Phone number should be in international format."); 37 | } 38 | const postData = { 39 | countryCode: pn.regionCode, 40 | dialingCode: pn.countryCode, 41 | phoneNumber: pn.number.significant, 42 | requestId: json_data.requestId, 43 | token: otp, 44 | }; 45 | const options = { 46 | method: "POST", 47 | headers: { 48 | "content-type": "application/json; charset=UTF-8", 49 | "accept-encoding": "gzip", 50 | "user-agent": "Truecaller/11.75.5 (Android;10)", 51 | clientsecret: "lvc22mp3l1sfv6ujg83rd17btt", 52 | }, 53 | url: "https://account-asia-south1.truecaller.com/v1/verifyOnboardingOtp", 54 | data: postData, 55 | }; 56 | const res = await axios(options); 57 | return res.data; 58 | } 59 | export { verifyOtp }; 60 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # TruecallerJS 2 | 3 | [![NPM version](https://img.shields.io/npm/v/truecallerjs.svg)](https://www.npmjs.com/package/truecallerjs) 4 | [![GIT Stars](https://img.shields.io/github/stars/sumithemmadi/truecallerjs)](https://github.com/sumithemmadi/truecallerjs/) 5 | [![Download](https://img.shields.io/npm/dt/truecallerjs.svg)](https://github.com/sumithemmadi/truecallerjs) 6 | [![GitHub Sponsors](https://img.shields.io/github/sponsors/sumithemmadi)](https://github.com/sumithemmadi/truecallerjs) 7 | [![LICENSE](https://img.shields.io/npm/l/truecallerjs.svg)](https://github.com/sumithemmadi/truecallerjs/blob/main/LICENSE) 8 | [![Maintenance](https://img.shields.io/npms-io/maintenance-score/truecallerjs)](https://github.com/sumithemmadi/truecallerjs) 9 | [![Issues](https://img.shields.io/github/issues/sumithemmadi/truecallerjs)](https://github.com/sumithemmadi/truecallerjs/issues) 10 | 11 | 12 | - The truecallerjs package allows you to integrate Truecaller functionality into your JavaScript applications. It provides methods for login and OTP verification. 13 | 14 | ## Installation 15 | 16 | - To install the truecallerjs package, run the following command: 17 | 18 | ```bash 19 | npm install truecallerjs 20 | ``` 21 | 22 | ## Login 23 | 24 | The `login` function is used to log in to the Truecaller service. It takes a phone number in international format as a parameter and returns a JSON object containing the login request details. 25 | 26 | Method Signature 27 | 28 | ```bash 29 | truecallerjs.login(phonenumber) 30 | ``` 31 | 32 | - phonenumber (String): The phone number in international format. 33 | 34 | ### Return Value 35 | 36 | The function returns a Promise that resolves to a JSON object with the following properties: 37 | 38 | - `status` (Number): The status code of the login request. Possible values are 1 (OTP sent successfully) or 9 (request in pending). 39 | - `message` (String): A message indicating the status of the login request. 40 | - `domain` (String): The domain associated with the phone number. 41 | - `parsedPhoneNumber` (Number): The phone number without the country code. 42 | - `parsedCountryCode` (String): The country code associated with the phone number. 43 | - `requestId` (String): The unique identifier for the login request. 44 | - `method` (String): The method used for sending the OTP (e.g., "sms"). 45 | - `tokenTtl` (Number): The time-to-live (TTL) value for the OTP token in seconds. 46 | 47 | ### Example 48 | 49 | ```js 50 | import truecallerjs, { LoginResponse } from "truecallerjs"; 51 | 52 | async function performLogin(): Promise { 53 | try { 54 | const phoneNumber: string = "+919912345678"; 55 | const json_data: LoginResponse = await truecallerjs.login(phoneNumber); 56 | 57 | // Example response: 58 | // { 59 | // "status": 1, 60 | // "message": "Sent", 61 | // "domain": "noneu", 62 | // "parsedPhoneNumber": 919912345678, 63 | // "parsedCountryCode": "IN", 64 | // "requestId": "6fe0eba6-acds-24dc-66de-15b3fba349c3", 65 | // "method": "sms", 66 | // "tokenTtl": 300 67 | // } 68 | 69 | if (json_data.status === 1 || json_data.status === 9) { 70 | // OTP sent successfully 71 | // Handle the response accordingly 72 | console.log("OTP sent successfully"); 73 | console.log("Request ID:", json_data.requestId); 74 | console.log("Token TTL:", json_data.tokenTtl); 75 | } else if (json_data.status === 6 || json_data.status === 5) { 76 | // Verification attempts exceeded 77 | // Handle the response accordingly 78 | console.log("Verification attempts exceeded"); 79 | console.log("Status:", json_data.status); 80 | console.log("Message:", json_data.message); 81 | } else { 82 | // Unknown response 83 | // Handle the response accordingly 84 | console.log("Unknown response"); 85 | console.log("Status:", json_data.status); 86 | console.log("Message:", json_data.message); 87 | } 88 | } catch (error) { 89 | console.error("Error occurred:", error); 90 | } 91 | } 92 | 93 | performLogin(); 94 | ``` 95 | 96 | > **Note** : Make sure to replace +919912345678 with the actual phone number you want to use. 97 | 98 | | status | message | 99 | | ----------|---------------------------------| 100 | | 1 | OTP sent successfully | 101 | | 9 | Request in pending | 102 | | 6 or 5 | Verification Attempts Exceeded | 103 | 104 | - Save this json in a file or store in a variable. This json will be used to verify OTP in `verifyOtp()` function. 105 | 106 | - OTP Verification 107 | 108 | - The verifyOtp function is used to verify the mobile number with the OTP (One-Time Password) received. 109 | 110 | ```js 111 | import truecallerjs, { LoginResponse } from "truecallerjs"; 112 | 113 | async function performOtpVerification(): Promise { 114 | try { 115 | const phoneNumber: string = "+919912345678"; 116 | const json_data: LoginResponse = await truecallerjs.login(phoneNumber); 117 | 118 | // Example response from login: 119 | // { 120 | // "status": 1, 121 | // "message": "Sent", 122 | // "domain": "noneu", 123 | // "parsedPhoneNumber": 919912345678, 124 | // "parsedCountryCode": "IN", 125 | // "requestId": "6fe0eba6-acds-24dc-66de-15b3fba349c3", 126 | // "method": "sms", 127 | // "tokenTtl": 300 128 | // } 129 | 130 | const otp: string = "123456"; // Replace with the actual OTP 131 | 132 | const res: object = await truecallerjs.verifyOtp( 133 | phoneNumber, 134 | json_data, 135 | otp 136 | ); 137 | 138 | console.log(res); 139 | 140 | // Example response from OTP verification: 141 | // { 142 | // "status": 2, 143 | // "message": "Verified", 144 | // "installationId": "a1k07--Vgdfyvv_rftf5uuudhuhnkljyvvtfftjuhbuijbhug", 145 | // "ttl": 259200, 146 | // "userId": 1234567890123456789, 147 | // "suspended": false, 148 | // "phones": [ 149 | // { 150 | // "phoneNumber": 919912345678, 151 | // "countryCode": "IN", 152 | // "priority": 1 153 | // } 154 | // ] 155 | // } 156 | 157 | if (res.status === 2 && !res.suspended) { 158 | // LOGIN SUCCESSFUL 159 | console.log("Login successful"); 160 | console.log("Installation ID:", res.installationId); 161 | console.log("User ID:", res.userId); 162 | } else if (res.status === 11) { 163 | // INVALID OTP 164 | console.log("Invalid OTP"); 165 | console.log("Status:", res.status); 166 | console.log("Message:", res.message); 167 | } else if (res.status === 7) { 168 | // RETRIES LIMIT EXCEEDED 169 | console.log("Retries limit exceeded"); 170 | console.log("Status:", res.status); 171 | console.log("Message:", res.message); 172 | } else if (res.suspended) { 173 | // ACCOUNT SUSPENDED 174 | console.log("Account suspended"); 175 | console.log("Status:", res.status); 176 | console.log("Message:", res.message); 177 | } else { 178 | // UNKNOWN RESPONSE 179 | console.log("Unknown response"); 180 | console.log("Message:", res.message); 181 | } 182 | } catch (error) { 183 | console.error("Error occurred:", error); 184 | } 185 | } 186 | 187 | performOtpVerification(); 188 | ``` 189 | 190 | | status | message | 191 | | ----------|---------------------------------| 192 | | 2 | Login Successful | 193 | | 11 | Invalid OTP | 194 | | 7 | OTP Retries exceeded | 195 | 196 | Make sure to replace phonenumber with the actual phone number, json_data with the JSON response obtained from the login function, and otp with the actual OTP received. 197 | 198 | The `res` variable will contain the JSON response from the OTP verification request. You can access the properties of the response to handle different scenarios: 199 | 200 | - If `res.status` is 2 and `res.suspended` is `false`, it means the login was successful. 201 | `res.installationId`, `res.suspended`, `res.phones[0].phoneNumber`, and `res.phones[0].countryCode` properties for further processing. 202 | 203 | - If `res.status` is `11`, it means the OTP entered is invalid. 204 | 205 | - If `res.status` is `7`, it means the number of OTP verification retries has exceeded the limit. 206 | 207 | - If `res.suspended` is `true`, it means the account is suspended. 208 | 209 | - For any other response, you can check `res.status` and res.message for more information. 210 | 211 | ### Simple Example of Searching Number 212 | 213 | - Normal search for a phone number. 214 | 215 | ```js 216 | import truecallerjs, { SearchData, Format } from "truecallerjs"; 217 | 218 | async function performTruecallerSearch(): Promise { 219 | const searchData: SearchData = { 220 | number: "9912345678", 221 | countryCode: "IN", 222 | installationId: "a1k07--Vgdfyvv_rftf5uuudhuhnkljyvvtfftjuhbuijbhug", 223 | }; 224 | 225 | try { 226 | const response: Format = await truecallerjs.search(searchData); 227 | console.log(response.json()); 228 | 229 | // Additional response methods: 230 | // console.log(response.xml()); 231 | // console.log(response.yaml()); 232 | // console.log(response.text()); 233 | 234 | // Example of available data from the response: 235 | console.log(response.getName()); // "Sumith Emmadi" 236 | console.log(response.getAlternateName()); // "sumith" 237 | console.log(response.getAddresses()); // {....} 238 | console.log(response.getEmailId()); // example@domain.com 239 | console.log(response.getCountryDetails()); // {...} 240 | } catch (error) { 241 | console.error("Error occurred:", error); 242 | } 243 | } 244 | 245 | performTruecallerSearch(); 246 | ``` 247 | 248 | - `number` : Phone number 249 | - `countryCode` : Country code to use by default If any phone number is not in e164 format(Internation format). Eg: Country code for India is "IN". 250 | - `installationId` : InstallationId Here, you need to login first to use it. Use the truecallerjs login command to login to your account. 251 | - 252 | 253 | In the above example, the `truecallerjs` package is used to search for a phone number. The `search_data` object contains the necessary parameters, including the number, country code, and installation ID. The response from the `truecallerjs.search()` function provides various methods to access the returned data. 254 | 255 | > **Note** : Make sure to log in using the `truecallerjs login` command and obtain your installation ID using the `truecallerjs -i` command. 256 | 257 | ### `response` Object 258 | 259 | The `response` object represents the response obtained from a query. It provides various methods and properties to access and manipulate the response data. 260 | 261 | #### Methods 262 | 263 | - `response.json(color)` 264 | - Parameters: 265 | - `color` (Boolean): Indicates whether to add color formatting to the JSON output. 266 | - Returns: JSON response as a string. 267 | - Description: This method returns the JSON response as a string. The optional `color` parameter determines whether to include color formatting in the output. 268 | 269 | - `response.xml(color)` 270 | - Parameters: 271 | - `color` (Boolean): Indicates whether to add color formatting to the XML output. 272 | - Returns: XML output as a string. 273 | - Description: This method returns the XML output as a string. The optional `color` parameter determines whether to include color formatting in the output. 274 | 275 | - `response.yaml(color)` 276 | - Parameters: 277 | - `color` (Boolean): Indicates whether to add color formatting to the YAML output. 278 | - Returns: YAML output as a string. 279 | - Description: This method returns the YAML output as a string. The optional `color` parameter determines whether to include color formatting in the output. 280 | 281 | - `response.text(color, space)` 282 | - Parameters: 283 | - `color` (Boolean): Indicates whether to add color formatting to the JSON output. 284 | - `space` (Boolean): Indicates whether to include spacing between keys and values in the JSON output. 285 | - Returns: JSON response as a string. 286 | - Description: This method returns the JSON response as a string. The optional `color` parameter determines whether to include color formatting in the output, and the `space` parameter determines whether to include spacing between keys and values. 287 | 288 | #### Properties 289 | 290 | - `response.getName()` 291 | - Returns: The name associated with the response. 292 | - Description: This method retrieves the name associated with the response. 293 | 294 | - `response.getAlternateName()` 295 | - Returns: The alternate name associated with the response. 296 | - Description: This method retrieves the alternate name associated with the response. 297 | 298 | - `response.getAddresses()` 299 | - Returns: The addresses associated with the response. 300 | - Description: This method retrieves the addresses associated with the response. The details of the addresses can be accessed using the returned object. 301 | 302 | - `response.getEmailId()` 303 | - Returns: The email ID associated with the response. 304 | - Description: This method retrieves the email ID associated with the response. 305 | 306 | - `response.getCountryDetails()` 307 | - Returns: The country details associated with the response. 308 | - Description: This method retrieves the country details associated with the response. The details can be accessed using the returned object. 309 | 310 | ### Bulk Search on Multiple Phone Numbers 311 | 312 | The `truecallerjs` package also supports bulk search on multiple phone numbers: 313 | 314 | ```js 315 | import truecallerjs, { BulkSearchData, Format } from "truecallerjs"; 316 | 317 | async function performBulkTruecallerSearch(): Promise { 318 | const countryCode: string = "IN"; 319 | const installationId: string = "a1k07--Vgdfyvv_rftf5uuudhuhnkljyvvtfftjuhbuijbhug"; 320 | const phoneNumbers: string = "+9912345678,+14051234567,+919987654321"; 321 | 322 | try { 323 | const response: BulkSearchData = await truecallerjs.bulkSearch(phoneNumbers, countryCode, installationId); 324 | console.log(response); 325 | } catch (error) { 326 | console.error("Error occurred:", error); 327 | } 328 | } 329 | 330 | performBulkTruecallerSearch(); 331 | ``` 332 | 333 | In this example, the `truecallerjs.bulkSearch()` function is used to perform bulk searches on multiple phone numbers. The `phoneNumbers` parameter should contain the phone numbers separated by commas. The `countryCode` and `installationId` parameters are used to specify the default country code and installation ID, respectively. 334 | 335 | > **Note** : Make sure to log in using the `truecallerjs login` command and obtain your installation ID using the `truecallerjs -i` command. 336 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * For a detailed explanation regarding each configuration property, visit: 3 | * https://jestjs.io/docs/configuration 4 | */ 5 | 6 | import type { Config } from "jest"; 7 | 8 | const config: Config = { 9 | // All imported modules in your tests should be mocked automatically 10 | // automock: false, 11 | 12 | // Stop running tests after `n` failures 13 | // bail: 0, 14 | 15 | // The directory where Jest should store its cached dependency information 16 | // cacheDirectory: "/tmp/jest_rs", 17 | 18 | // Automatically clear mock calls, instances, contexts and results before every test 19 | clearMocks: true, 20 | 21 | // Indicates whether the coverage information should be collected while executing the test 22 | collectCoverage: true, 23 | 24 | // An array of glob patterns indicating a set of files for which coverage information should be collected 25 | // collectCoverageFrom: undefined, 26 | 27 | // The directory where Jest should output its coverage files 28 | coverageDirectory: "coverage", 29 | 30 | // An array of regexp pattern strings used to skip coverage collection 31 | // coveragePathIgnorePatterns: [ 32 | // "/node_modules/" 33 | // ], 34 | 35 | // Indicates which provider should be used to instrument code for coverage 36 | // coverageProvider: "babel", 37 | 38 | // A list of reporter names that Jest uses when writing coverage reports 39 | // coverageReporters: [ 40 | // "json", 41 | // "text", 42 | // "lcov", 43 | // "clover" 44 | // ], 45 | 46 | // An object that configures minimum threshold enforcement for coverage results 47 | // coverageThreshold: undefined, 48 | 49 | // A path to a custom dependency extractor 50 | // dependencyExtractor: undefined, 51 | 52 | // Make calling deprecated APIs throw helpful error messages 53 | // errorOnDeprecated: false, 54 | 55 | // The default configuration for fake timers 56 | // fakeTimers: { 57 | // "enableGlobally": false 58 | // }, 59 | 60 | // Force coverage collection from ignored files using an array of glob patterns 61 | // forceCoverageMatch: [], 62 | 63 | // A path to a module which exports an async function that is triggered once before all test suites 64 | // globalSetup: undefined, 65 | 66 | // A path to a module which exports an async function that is triggered once after all test suites 67 | // globalTeardown: undefined, 68 | 69 | // A set of global variables that need to be available in all test environments 70 | // globals: {}, 71 | 72 | // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. 73 | // maxWorkers: "50%", 74 | 75 | // An array of directory names to be searched recursively up from the requiring module's location 76 | // moduleDirectories: [ 77 | // "node_modules" 78 | // ], 79 | 80 | // An array of file extensions your modules use 81 | // moduleFileExtensions: [ 82 | // "js", 83 | // "mjs", 84 | // "cjs", 85 | // "jsx", 86 | // "ts", 87 | // "tsx", 88 | // "json", 89 | // "node" 90 | // ], 91 | 92 | // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module 93 | // moduleNameMapper: {}, 94 | 95 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader 96 | // modulePathIgnorePatterns: [], 97 | 98 | // Activates notifications for test results 99 | // notify: false, 100 | 101 | // An enum that specifies notification mode. Requires { notify: true } 102 | // notifyMode: "failure-change", 103 | 104 | // A preset that is used as a base for Jest's configuration 105 | // preset: undefined, 106 | 107 | // Run tests from one or more projects 108 | // projects: undefined, 109 | 110 | // Use this configuration option to add custom reporters to Jest 111 | // reporters: undefined, 112 | 113 | // Automatically reset mock state before every test 114 | // resetMocks: false, 115 | 116 | // Reset the module registry before running each individual test 117 | // resetModules: false, 118 | 119 | // A path to a custom resolver 120 | // resolver: undefined, 121 | 122 | // Automatically restore mock state and implementation before every test 123 | // restoreMocks: false, 124 | 125 | // The root directory that Jest should scan for tests and modules within 126 | // rootDir: undefined, 127 | 128 | // A list of paths to directories that Jest should use to search for files in 129 | // roots: [ 130 | // "" 131 | // ], 132 | 133 | // Allows you to use a custom runner instead of Jest's default test runner 134 | // runner: "jest-runner", 135 | 136 | // The paths to modules that run some code to configure or set up the testing environment before each test 137 | // setupFiles: [], 138 | 139 | // A list of paths to modules that run some code to configure or set up the testing framework before each test 140 | // setupFilesAfterEnv: [], 141 | 142 | // The number of seconds after which a test is considered as slow and reported as such in the results. 143 | // slowTestThreshold: 5, 144 | 145 | // A list of paths to snapshot serializer modules Jest should use for snapshot testing 146 | // snapshotSerializers: [], 147 | 148 | // The test environment that will be used for testing 149 | // testEnvironment: "jest-environment-node", 150 | 151 | // Options that will be passed to the testEnvironment 152 | // testEnvironmentOptions: {}, 153 | 154 | // Adds a location field to test results 155 | // testLocationInResults: false, 156 | 157 | // The glob patterns Jest uses to detect test files 158 | // testMatch: [ 159 | // "**/__tests__/**/*.[jt]s?(x)", 160 | // "**/?(*.)+(spec|test).[tj]s?(x)" 161 | // ], 162 | 163 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped 164 | // testPathIgnorePatterns: [ 165 | // "/node_modules/" 166 | // ], 167 | 168 | // The regexp pattern or array of patterns that Jest uses to detect test files 169 | // testRegex: [], 170 | 171 | // This option allows the use of a custom results processor 172 | // testResultsProcessor: undefined, 173 | 174 | // This option allows use of a custom test runner 175 | // testRunner: "jest-circus/runner", 176 | 177 | // A map from regular expressions to paths to transformers 178 | // transform: undefined, 179 | 180 | // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation 181 | // transformIgnorePatterns: [ 182 | // "/node_modules/", 183 | // "\\.pnp\\.[^\\/]+$" 184 | // ], 185 | 186 | // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them 187 | // unmockedModulePathPatterns: undefined, 188 | 189 | // Indicates whether each individual test should be reported during the run 190 | // verbose: undefined, 191 | 192 | // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode 193 | // watchPathIgnorePatterns: [], 194 | 195 | // Whether to use watchman for file crawling 196 | // watchman: true, 197 | }; 198 | 199 | export default config; 200 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "truecallerjs", 3 | "version": "2.2.0", 4 | "description": "TruecallerJS: A library for effortless retrieval of phone number details using the Truecaller API in Node.js, JavaScript, and TypeScript projects.", 5 | "main": "dist/cjs/index.js", 6 | "module": "dist/index.js", 7 | "type": "module", 8 | "exports": { 9 | ".": { 10 | "types": "./typings/index.d.ts", 11 | "import": "./dist/index.js", 12 | "require": "./dist/cjs/index.js" 13 | }, 14 | "./package.json": "./package.json" 15 | }, 16 | "types": "./typings/index.d.ts", 17 | "bin": { 18 | "truecallerjs": "./dist/cli.js" 19 | }, 20 | "scripts": { 21 | "build": "rm -rf ./dist && tsc", 22 | "build:cjs": "tsc && npm run echo:type-cjs", 23 | "echo:type-cjs": "echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json", 24 | "cli": "NODE_OPTIONS='--es-module-specifier-resolution=node' node dist/cli.js login", 25 | "eslint": "npx eslint .", 26 | "prettier": "npx prettier --write .", 27 | "start": "NODE_OPTIONS='--es-module-specifier-resolution=node' node dist/cli.js -s 9912345678", 28 | "test": "export TEST_PHONE_NUMBER=&(echo -e '+91$((RANDOM%9000000000+1000000000))') && export TEST_INSTALLATION_ID=$(truecallerjs -i -r) && jest" 29 | }, 30 | "directories": { 31 | "test": "test" 32 | }, 33 | "repository": { 34 | "type": "git", 35 | "url": "git+https://github.com/sumithemmadi/truecallerjs.git" 36 | }, 37 | "keywords": [ 38 | "truecallerjs", 39 | "truecaller", 40 | "phone", 41 | "number", 42 | "caller", 43 | "details", 44 | "name", 45 | "email", 46 | "search", 47 | "lookup", 48 | "Information", 49 | "gathering", 50 | "address" 51 | ], 52 | "author": "Sumith Emmadi (sumithemmadi)", 53 | "license": "MIT", 54 | "bugs": { 55 | "url": "https://github.com/sumithemmadi/truecallerjs/issues" 56 | }, 57 | "homepage": "https://github.com/sumithemmadi/truecallerjs#readme", 58 | "dependencies": { 59 | "awesome-phonenumber": "^5.10.0", 60 | "axios": "^1.4.0", 61 | "chalk": "^5.3.0", 62 | "inquirer": "^9.2.9", 63 | "json-colorizer": "^2.2.2", 64 | "json-to-plain-text": "^1.1.2", 65 | "json-to-pretty-yaml": "^1.2.2", 66 | "ts-node": "^10.9.1", 67 | "xml2js": "^0.6.2", 68 | "yargs": "^17.7.2", 69 | "yargs-parser": "^21.1.1" 70 | }, 71 | "devDependencies": { 72 | "@babel/preset-env": "^7.22.9", 73 | "@types/inquirer": "^9.0.3", 74 | "@types/node": "^20.4.5", 75 | "@types/xml2js": "^0.4.11", 76 | "@types/yargs": "^17.0.24", 77 | "@typescript-eslint/eslint-plugin": "^6.2.1", 78 | "@typescript-eslint/parser": "^6.2.1", 79 | "babel-jest": "^29.6.2", 80 | "eslint": "^8.46.0", 81 | "install": "^0.13.0", 82 | "jest": "^29.6.2", 83 | "typescript": "^5.1.6" 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/cli.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* 4 | // MIT License 5 | 6 | // Copyright (c) 2021 Emmadi Sumith Kumar 7 | 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | */ 26 | 27 | import yargs, { Arguments } from "yargs"; 28 | import { hideBin } from "yargs/helpers"; 29 | import fs from "fs"; 30 | import chalk from "chalk"; 31 | import path from "path"; 32 | import inquirer from "inquirer"; 33 | import { parsePhoneNumber } from "awesome-phonenumber"; 34 | import os from "os"; 35 | import { login } from "./login.js"; 36 | import { verifyOtp } from "./verifyOtp.js"; 37 | import { search, bulkSearch } from "./search.js"; 38 | import colorizeJson from "json-colorizer"; 39 | 40 | const homePath = os.homedir(); 41 | const truecallerjsAuthDirPath = path.join(homePath, ".config", "truecallerjs"); 42 | const requestFilePath = path.join(truecallerjsAuthDirPath, "request.json"); 43 | const authKeyFilePath = path.join(truecallerjsAuthDirPath, "authkey.json"); 44 | 45 | interface VerifyOtpResponse { 46 | status?: number; 47 | suspended?: boolean; 48 | installationId?: string; 49 | message?: string; 50 | } 51 | 52 | const runCLI = async () => { 53 | const args: Arguments = yargs(hideBin(process.argv)) 54 | .usage( 55 | "Usage: \n$0 login (Login to truecaller).\n$0 -s [number] (command to search a number).", 56 | ) 57 | .option("search", { 58 | alias: "s", 59 | description: "To search caller name and related information of a number", 60 | }) 61 | .option("raw", { 62 | alias: "r", 63 | description: "Print's raw output", 64 | type: "boolean", 65 | }) 66 | .option("bulksearch", { 67 | alias: "bs", 68 | description: "Make a bulk number search", 69 | }) 70 | .option("name", { 71 | alias: "n", 72 | description: "Print's user name of phone number ", 73 | type: "boolean", 74 | }) 75 | .option("email", { 76 | alias: "e", 77 | description: "Print's email assigned to the phonenumber", 78 | type: "boolean", 79 | }) 80 | .option("json", { 81 | description: "print's output in json", 82 | type: "boolean", 83 | }) 84 | .option("xml", { 85 | description: "print's output in XML", 86 | type: "boolean", 87 | }) 88 | .option("yaml", { 89 | description: "Print's output in YAML", 90 | type: "boolean", 91 | }) 92 | .option("text", { 93 | description: "Print's output as plain text(TXT)", 94 | type: "boolean", 95 | }) 96 | .option("nc", { 97 | alias: "no_color", 98 | description: "Print without color", 99 | type: "boolean", 100 | }) 101 | .option("installationid", { 102 | alias: "i", 103 | description: "shows your InstallationId", 104 | type: "boolean", 105 | }) 106 | .option("verbose", { 107 | alias: "v", 108 | description: "Show additional information", 109 | type: "count", 110 | }) 111 | .help() 112 | .alias("help", "h") 113 | .parseSync(); 114 | 115 | if (args._.includes("login") && !args.s && !args.bs) { 116 | // Create the auth directory for truecallerjs if it doesn't exist 117 | if (!fs.existsSync(truecallerjsAuthDirPath)) { 118 | try { 119 | fs.mkdirSync(truecallerjsAuthDirPath, { recursive: true }); 120 | } catch (error) { 121 | console.log(error); 122 | process.exit(1); 123 | } 124 | } 125 | 126 | // Starts here 127 | if (args._[0] === "login" && args._.length <= 2) { 128 | console.log( 129 | chalk.yellow.bold( 130 | "Login\n\n Enter mobile number in International Format\n Example : ", 131 | ) + 132 | chalk.magenta("+919912345678") + 133 | ".\n", 134 | ); 135 | 136 | const inputNumber = await inquirer.prompt({ 137 | type: "input", 138 | name: "phonenumber", 139 | message: "Enter your phone number :", 140 | validate: async (input) => { 141 | const check = parsePhoneNumber(input); 142 | 143 | if (input !== (check?.number?.e164 ?? "")) { 144 | return "Enter a valid phone number in International Format"; 145 | } 146 | 147 | if (!check?.valid) { 148 | return "Invalid Phone Number"; 149 | } 150 | 151 | return true; 152 | }, 153 | }); 154 | 155 | const pn = parsePhoneNumber(inputNumber.phonenumber); 156 | 157 | let response; 158 | let new_req = true; 159 | 160 | if (fs.existsSync(requestFilePath)) { 161 | const fileData = JSON.parse(fs.readFileSync(requestFilePath, "utf8")); 162 | if ( 163 | "parsedPhoneNumber" in fileData && 164 | `+${fileData.parsedPhoneNumber}` == pn?.number?.e164 165 | ) { 166 | console.log( 167 | chalk.magenta( 168 | "\nPrevious request was found for this mobile number.\n", 169 | ), 170 | ); 171 | const x = await inquirer.prompt({ 172 | type: "confirm", 173 | name: "status", 174 | message: "Do you want to enter previous OTP ", 175 | }); 176 | 177 | if (x.status) { 178 | new_req = false; 179 | response = fileData; 180 | } 181 | } 182 | } 183 | 184 | if (new_req) { 185 | response = await login(String(pn?.number?.e164)); 186 | console.log( 187 | chalk.yellow( 188 | `Sending OTP to ${chalk.green(pn?.number?.e164 ?? "")}.`, 189 | ), 190 | ); 191 | } 192 | 193 | if ( 194 | response.status == 1 || 195 | response.status == 9 || 196 | response.message == "Sent" 197 | ) { 198 | // Otp sent 199 | try { 200 | fs.writeFileSync(requestFilePath, JSON.stringify(response, null, 4)); 201 | 202 | if (new_req) { 203 | console.log(chalk.green("OTP sent successfully.")); 204 | } 205 | 206 | const token = await inquirer.prompt({ 207 | type: "input", 208 | name: "otp", 209 | message: "Enter Received OTP:", 210 | validate: async (input) => { 211 | const isnum = /^\d+$/.test(String(input)); 212 | 213 | if (input.length !== 6 || !isnum) { 214 | return "Enter a valid 6-digit OTP."; 215 | } 216 | return true; 217 | }, 218 | }); 219 | 220 | const response1: VerifyOtpResponse = await verifyOtp( 221 | String(pn?.number?.e164), 222 | response, 223 | token.otp, 224 | ); 225 | 226 | if (response1.status === 2 && !response1.suspended) { 227 | console.log( 228 | chalk.yellow.bold("Your installationId: ") + 229 | chalk.green(response1.installationId), 230 | ); 231 | console.log( 232 | `This is the installationId: ${chalk.green( 233 | response1.installationId, 234 | )} used to authenticate with Truecaller.`, 235 | ); 236 | 237 | // Save the file 238 | fs.writeFileSync( 239 | authKeyFilePath, 240 | JSON.stringify(response1, null, 3), 241 | ); 242 | 243 | console.log(chalk.green("Logged in successfully.")); 244 | fs.unlinkSync(requestFilePath); 245 | } else if (response1.status === 11) { 246 | console.log(chalk.red("! Invalid OTP")); 247 | console.log( 248 | `OTP not valid. Enter the 6-digit OTP received on ${pn?.number?.e164}.`, 249 | ); 250 | } else if (response1.status === 7) { 251 | console.log(chalk.red("Retries limit exceeded")); 252 | console.log( 253 | `Retries on secret code reached for ${pn?.number?.e164}.`, 254 | ); 255 | } else if (response1.suspended) { 256 | console.log(chalk.red("Oops... Your account is suspended.")); 257 | console.log("Your account has been suspended by Truecaller."); 258 | } else if ("message" in response1) { 259 | console.log(chalk.red(response1.message)); 260 | } else { 261 | console.log(JSON.stringify(response1, null, 4)); 262 | } 263 | } catch (error: unknown) { 264 | if (error instanceof Error) { 265 | console.log(chalk.red(error.message)); 266 | } else { 267 | console.log(chalk.red("An error occurred.")); 268 | } 269 | process.exit(1); 270 | } 271 | } else if (response.status == 6 || response.status == 5) { 272 | if (fs.existsSync(requestFilePath)) { 273 | fs.unlinkSync(requestFilePath); 274 | } 275 | console.log( 276 | chalk.red( 277 | "You have exceeded the limit of verification attempts.\nPlease try again after some time.", 278 | ), 279 | ); 280 | } else { 281 | console.log(chalk.red(response.message)); 282 | } 283 | } 284 | } else if (args.s && !args.bs && !args._.includes("login") && !args.i) { 285 | if (!fs.existsSync(authKeyFilePath)) { 286 | console.error(chalk.magenta.bold("Please login to your account.")); 287 | process.exit(); 288 | } 289 | try { 290 | const data = fs.readFileSync(authKeyFilePath, "utf8"); 291 | const jsonAuthKey = JSON.parse(data); 292 | const countryCode = jsonAuthKey.phones[0].countryCode; 293 | const installationId = jsonAuthKey.installationId; 294 | 295 | const search_result = await search({ 296 | number: String(args.s), 297 | countryCode, 298 | installationId, 299 | }); 300 | 301 | if (args.json || args.xml || args.text || args.yaml) { 302 | if (args.json && !args.xml && !args.text && !args.yaml) { 303 | if (args.r) { 304 | console.log( 305 | !args.nc 306 | ? colorizeJson(JSON.stringify(search_result.json()), { 307 | colors: { 308 | STRING_KEY: "blue", 309 | STRING_LITERAL: "green", 310 | NUMBER_LITERAL: "magenta", 311 | }, 312 | }) 313 | : JSON.stringify(search_result.json()), 314 | ); 315 | } else { 316 | console.log( 317 | !args.nc 318 | ? colorizeJson(JSON.stringify(search_result.json()), { 319 | pretty: true, 320 | colors: { 321 | STRING_KEY: "blue", 322 | STRING_LITERAL: "green", 323 | NUMBER_LITERAL: "magenta", 324 | }, 325 | }) 326 | : JSON.stringify(search_result.json(), null, 2), 327 | ); 328 | } 329 | } else if (args.xml && !args.json && !args.text && !args.yaml) { 330 | console.log(search_result.xml(!args.nc)); 331 | } else if (args.yaml && !args.xml && !args.text && !args.json) { 332 | console.log(search_result.yaml(!args.nc)); 333 | } else { 334 | console.log(search_result.text(!args.nc, true)); 335 | } 336 | } else { 337 | if (args.n && !args.r && !args.e) { 338 | console.log( 339 | chalk.blue.bold("Name"), 340 | " : ", 341 | chalk.green(search_result.getName()), 342 | ); 343 | } else if (args.n && args.r && !args.e) { 344 | console.log(search_result.getName()); 345 | } else if (!args.n && !args.r && args.e) { 346 | console.log( 347 | chalk.blue.bold("Email"), 348 | " : ", 349 | chalk.green(search_result.getEmailId()), 350 | ); 351 | } else if (!args.n && args.r && args.e) { 352 | console.log(search_result.getEmailId()); 353 | } else { 354 | console.log(search_result.text(!args.nc, true)); 355 | } 356 | } 357 | } catch (error: unknown) { 358 | if (error instanceof Error) { 359 | console.log(chalk.red(error.message)); 360 | } else { 361 | console.log(chalk.red("An error occurred.")); 362 | } 363 | process.exit(1); 364 | } 365 | } else if (args.bs && !args._.includes("login") && !args.i) { 366 | if (!fs.existsSync(authKeyFilePath)) { 367 | console.error(chalk.magenta.bold("Please login to your account.")); 368 | process.exit(1); 369 | } 370 | 371 | try { 372 | const data = fs.readFileSync(authKeyFilePath, "utf8"); 373 | const jsonAuthKey = JSON.parse(data); 374 | 375 | const countryCode = jsonAuthKey.phones[0].countryCode; 376 | const installationId = jsonAuthKey.installationId; 377 | 378 | const searchResult = await bulkSearch( 379 | String(args?.bs), 380 | countryCode, 381 | installationId, 382 | ); 383 | 384 | if (args.r) { 385 | console.log( 386 | !args.nc 387 | ? colorizeJson(JSON.stringify(searchResult), { 388 | colors: { 389 | STRING_KEY: "blue", 390 | STRING_LITERAL: "green", 391 | NUMBER_LITERAL: "magenta", 392 | }, 393 | }) 394 | : JSON.stringify(searchResult), 395 | ); 396 | } else { 397 | console.log( 398 | !args.nc 399 | ? colorizeJson(JSON.stringify(searchResult), { 400 | pretty: true, 401 | colors: { 402 | STRING_KEY: "blue", 403 | STRING_LITERAL: "green", 404 | NUMBER_LITERAL: "magenta", 405 | }, 406 | }) 407 | : JSON.stringify(searchResult, null, 2), 408 | ); 409 | } 410 | } catch (error: unknown) { 411 | if (error instanceof Error) { 412 | console.log(chalk.red(error.message)); 413 | } else { 414 | console.log(chalk.red("An error occurred.")); 415 | } 416 | process.exit(1); 417 | } 418 | } else if (args.i && !args.s) { 419 | if (!fs.existsSync(authKeyFilePath)) { 420 | console.error(chalk.magenta.bold("Please login to your account.")); 421 | process.exit(1); 422 | } 423 | 424 | try { 425 | const data = fs.readFileSync(authKeyFilePath, "utf8"); 426 | const jsonAuthKey = JSON.parse(data); 427 | // let countryCode = jsonAuthKey.phones[0].countryCode; 428 | const installationId = jsonAuthKey.installationId; 429 | if (args.r) { 430 | console.log(installationId); 431 | } else { 432 | args.nc 433 | ? console.log("Your InstallationId : " + installationId) 434 | : console.log( 435 | chalk.blue.bold("Your InstallationId") + 436 | " : " + 437 | chalk.green(installationId), 438 | ); 439 | } 440 | } catch (error: unknown) { 441 | if (error instanceof Error) { 442 | console.log(chalk.red(error.message)); 443 | } else { 444 | console.log(chalk.red("An error occurred.")); 445 | } 446 | process.exit(1); 447 | } 448 | } else { 449 | console.log(`Usage: 450 | ${chalk.green("truecallerjs")} login (Login to truecaller). 451 | ${chalk.green("truecallerjs")} -s [number] (command to search a number). 452 | 453 | Options: 454 | --version Show version number [boolean] 455 | -s, --search To search caller name and related information of a num 456 | ber 457 | -r, --raw Print's raw output [boolean] 458 | --bulksearch, --bs Make a bulk number search 459 | -n, --name Print's user name of phone number [boolean] 460 | -e, --email Print's email assigned to the phonenumber [boolean] 461 | --json print's output in json [boolean] 462 | --xml print's output in XML [boolean] 463 | --yaml Print's output in YAML [boolean] 464 | --text Print's output as plain text(TXT) [boolean] 465 | --nc, --no_color Print without color [boolean] 466 | -i, --installationid shows your InstallationId [boolean] 467 | -v, --verbose Show additional information [count] 468 | -h, --help Show help [boolean] 469 | 470 | Repository => https://github.com/sumithemmadi/truecallerjs 471 | `); 472 | } 473 | }; 474 | 475 | runCLI(); 476 | -------------------------------------------------------------------------------- /src/data/continents.json: -------------------------------------------------------------------------------- 1 | { 2 | "AF": "Africa", 3 | "AN": "Antarctica", 4 | "AS": "Asia", 5 | "EU": "Europe", 6 | "NA": "North America", 7 | "OC": "Oceania", 8 | "SA": "South America" 9 | } 10 | -------------------------------------------------------------------------------- /src/data/languages.json: -------------------------------------------------------------------------------- 1 | { 2 | "aa": { 3 | "name": "Afar", 4 | "native": "Afar" 5 | }, 6 | "ab": { 7 | "name": "Abkhazian", 8 | "native": "Аҧсуа" 9 | }, 10 | "af": { 11 | "name": "Afrikaans", 12 | "native": "Afrikaans" 13 | }, 14 | "ak": { 15 | "name": "Akan", 16 | "native": "Akana" 17 | }, 18 | "am": { 19 | "name": "Amharic", 20 | "native": "አማርኛ" 21 | }, 22 | "an": { 23 | "name": "Aragonese", 24 | "native": "Aragonés" 25 | }, 26 | "ar": { 27 | "name": "Arabic", 28 | "native": "العربية", 29 | "rtl": 1 30 | }, 31 | "as": { 32 | "name": "Assamese", 33 | "native": "অসমীয়া" 34 | }, 35 | "av": { 36 | "name": "Avar", 37 | "native": "Авар" 38 | }, 39 | "ay": { 40 | "name": "Aymara", 41 | "native": "Aymar" 42 | }, 43 | "az": { 44 | "name": "Azerbaijani", 45 | "native": "Azərbaycanca / آذربايجان" 46 | }, 47 | "ba": { 48 | "name": "Bashkir", 49 | "native": "Башҡорт" 50 | }, 51 | "be": { 52 | "name": "Belarusian", 53 | "native": "Беларуская" 54 | }, 55 | "bg": { 56 | "name": "Bulgarian", 57 | "native": "Български" 58 | }, 59 | "bh": { 60 | "name": "Bihari", 61 | "native": "भोजपुरी" 62 | }, 63 | "bi": { 64 | "name": "Bislama", 65 | "native": "Bislama" 66 | }, 67 | "bm": { 68 | "name": "Bambara", 69 | "native": "Bamanankan" 70 | }, 71 | "bn": { 72 | "name": "Bengali", 73 | "native": "বাংলা" 74 | }, 75 | "bo": { 76 | "name": "Tibetan", 77 | "native": "བོད་ཡིག / Bod skad" 78 | }, 79 | "br": { 80 | "name": "Breton", 81 | "native": "Brezhoneg" 82 | }, 83 | "bs": { 84 | "name": "Bosnian", 85 | "native": "Bosanski" 86 | }, 87 | "ca": { 88 | "name": "Catalan", 89 | "native": "Català" 90 | }, 91 | "ce": { 92 | "name": "Chechen", 93 | "native": "Нохчийн" 94 | }, 95 | "ch": { 96 | "name": "Chamorro", 97 | "native": "Chamoru" 98 | }, 99 | "co": { 100 | "name": "Corsican", 101 | "native": "Corsu" 102 | }, 103 | "cr": { 104 | "name": "Cree", 105 | "native": "Nehiyaw" 106 | }, 107 | "cs": { 108 | "name": "Czech", 109 | "native": "Čeština" 110 | }, 111 | "cu": { 112 | "name": "Old Church Slavonic / Old Bulgarian", 113 | "native": "словѣньскъ / slověnĭskŭ" 114 | }, 115 | "cv": { 116 | "name": "Chuvash", 117 | "native": "Чăваш" 118 | }, 119 | "cy": { 120 | "name": "Welsh", 121 | "native": "Cymraeg" 122 | }, 123 | "da": { 124 | "name": "Danish", 125 | "native": "Dansk" 126 | }, 127 | "de": { 128 | "name": "German", 129 | "native": "Deutsch" 130 | }, 131 | "dv": { 132 | "name": "Divehi", 133 | "native": "ދިވެހިބަސް", 134 | "rtl": 1 135 | }, 136 | "dz": { 137 | "name": "Dzongkha", 138 | "native": "ཇོང་ཁ" 139 | }, 140 | "ee": { 141 | "name": "Ewe", 142 | "native": "Ɛʋɛ" 143 | }, 144 | "el": { 145 | "name": "Greek", 146 | "native": "Ελληνικά" 147 | }, 148 | "en": { 149 | "name": "English", 150 | "native": "English" 151 | }, 152 | "eo": { 153 | "name": "Esperanto", 154 | "native": "Esperanto" 155 | }, 156 | "es": { 157 | "name": "Spanish", 158 | "native": "Español" 159 | }, 160 | "et": { 161 | "name": "Estonian", 162 | "native": "Eesti" 163 | }, 164 | "eu": { 165 | "name": "Basque", 166 | "native": "Euskara" 167 | }, 168 | "fa": { 169 | "name": "Persian", 170 | "native": "فارسی", 171 | "rtl": 1 172 | }, 173 | "ff": { 174 | "name": "Peul", 175 | "native": "Fulfulde" 176 | }, 177 | "fi": { 178 | "name": "Finnish", 179 | "native": "Suomi" 180 | }, 181 | "fj": { 182 | "name": "Fijian", 183 | "native": "Na Vosa Vakaviti" 184 | }, 185 | "fo": { 186 | "name": "Faroese", 187 | "native": "Føroyskt" 188 | }, 189 | "fr": { 190 | "name": "French", 191 | "native": "Français" 192 | }, 193 | "fy": { 194 | "name": "West Frisian", 195 | "native": "Frysk" 196 | }, 197 | "ga": { 198 | "name": "Irish", 199 | "native": "Gaeilge" 200 | }, 201 | "gd": { 202 | "name": "Scottish Gaelic", 203 | "native": "Gàidhlig" 204 | }, 205 | "gl": { 206 | "name": "Galician", 207 | "native": "Galego" 208 | }, 209 | "gn": { 210 | "name": "Guarani", 211 | "native": "Avañe'ẽ" 212 | }, 213 | "gu": { 214 | "name": "Gujarati", 215 | "native": "ગુજરાતી" 216 | }, 217 | "gv": { 218 | "name": "Manx", 219 | "native": "Gaelg" 220 | }, 221 | "ha": { 222 | "name": "Hausa", 223 | "native": "هَوُسَ", 224 | "rtl": 1 225 | }, 226 | "he": { 227 | "name": "Hebrew", 228 | "native": "עברית", 229 | "rtl": 1 230 | }, 231 | "hi": { 232 | "name": "Hindi", 233 | "native": "हिन्दी" 234 | }, 235 | "ho": { 236 | "name": "Hiri Motu", 237 | "native": "Hiri Motu" 238 | }, 239 | "hr": { 240 | "name": "Croatian", 241 | "native": "Hrvatski" 242 | }, 243 | "ht": { 244 | "name": "Haitian", 245 | "native": "Krèyol ayisyen" 246 | }, 247 | "hu": { 248 | "name": "Hungarian", 249 | "native": "Magyar" 250 | }, 251 | "hy": { 252 | "name": "Armenian", 253 | "native": "Հայերեն" 254 | }, 255 | "hz": { 256 | "name": "Herero", 257 | "native": "Otsiherero" 258 | }, 259 | "ia": { 260 | "name": "Interlingua", 261 | "native": "Interlingua" 262 | }, 263 | "id": { 264 | "name": "Indonesian", 265 | "native": "Bahasa Indonesia" 266 | }, 267 | "ie": { 268 | "name": "Interlingue", 269 | "native": "Interlingue" 270 | }, 271 | "ig": { 272 | "name": "Igbo", 273 | "native": "Igbo" 274 | }, 275 | "ii": { 276 | "name": "Sichuan Yi", 277 | "native": "ꆇꉙ / 四川彝语" 278 | }, 279 | "ik": { 280 | "name": "Inupiak", 281 | "native": "Iñupiak" 282 | }, 283 | "io": { 284 | "name": "Ido", 285 | "native": "Ido" 286 | }, 287 | "is": { 288 | "name": "Icelandic", 289 | "native": "Íslenska" 290 | }, 291 | "it": { 292 | "name": "Italian", 293 | "native": "Italiano" 294 | }, 295 | "iu": { 296 | "name": "Inuktitut", 297 | "native": "ᐃᓄᒃᑎᑐᑦ" 298 | }, 299 | "ja": { 300 | "name": "Japanese", 301 | "native": "日本語" 302 | }, 303 | "jv": { 304 | "name": "Javanese", 305 | "native": "Basa Jawa" 306 | }, 307 | "ka": { 308 | "name": "Georgian", 309 | "native": "ქართული" 310 | }, 311 | "kg": { 312 | "name": "Kongo", 313 | "native": "KiKongo" 314 | }, 315 | "ki": { 316 | "name": "Kikuyu", 317 | "native": "Gĩkũyũ" 318 | }, 319 | "kj": { 320 | "name": "Kuanyama", 321 | "native": "Kuanyama" 322 | }, 323 | "kk": { 324 | "name": "Kazakh", 325 | "native": "Қазақша" 326 | }, 327 | "kl": { 328 | "name": "Greenlandic", 329 | "native": "Kalaallisut" 330 | }, 331 | "km": { 332 | "name": "Cambodian", 333 | "native": "ភាសាខ្មែរ" 334 | }, 335 | "kn": { 336 | "name": "Kannada", 337 | "native": "ಕನ್ನಡ" 338 | }, 339 | "ko": { 340 | "name": "Korean", 341 | "native": "한국어" 342 | }, 343 | "kr": { 344 | "name": "Kanuri", 345 | "native": "Kanuri" 346 | }, 347 | "ks": { 348 | "name": "Kashmiri", 349 | "native": "कश्मीरी / كشميري", 350 | "rtl": 1 351 | }, 352 | "ku": { 353 | "name": "Kurdish", 354 | "native": "Kurdî / كوردی", 355 | "rtl": 1 356 | }, 357 | "kv": { 358 | "name": "Komi", 359 | "native": "Коми" 360 | }, 361 | "kw": { 362 | "name": "Cornish", 363 | "native": "Kernewek" 364 | }, 365 | "ky": { 366 | "name": "Kyrgyz", 367 | "native": "Кыргызча" 368 | }, 369 | "la": { 370 | "name": "Latin", 371 | "native": "Latina" 372 | }, 373 | "lb": { 374 | "name": "Luxembourgish", 375 | "native": "Lëtzebuergesch" 376 | }, 377 | "lg": { 378 | "name": "Ganda", 379 | "native": "Luganda" 380 | }, 381 | "li": { 382 | "name": "Limburgian", 383 | "native": "Limburgs" 384 | }, 385 | "ln": { 386 | "name": "Lingala", 387 | "native": "Lingála" 388 | }, 389 | "lo": { 390 | "name": "Laotian", 391 | "native": "ລາວ / Pha xa lao" 392 | }, 393 | "lt": { 394 | "name": "Lithuanian", 395 | "native": "Lietuvių" 396 | }, 397 | "lu": { 398 | "name": "Luba-Katanga", 399 | "native": "Tshiluba" 400 | }, 401 | "lv": { 402 | "name": "Latvian", 403 | "native": "Latviešu" 404 | }, 405 | "mg": { 406 | "name": "Malagasy", 407 | "native": "Malagasy" 408 | }, 409 | "mh": { 410 | "name": "Marshallese", 411 | "native": "Kajin Majel / Ebon" 412 | }, 413 | "mi": { 414 | "name": "Maori", 415 | "native": "Māori" 416 | }, 417 | "mk": { 418 | "name": "Macedonian", 419 | "native": "Македонски" 420 | }, 421 | "ml": { 422 | "name": "Malayalam", 423 | "native": "മലയാളം" 424 | }, 425 | "mn": { 426 | "name": "Mongolian", 427 | "native": "Монгол" 428 | }, 429 | "mo": { 430 | "name": "Moldovan", 431 | "native": "Moldovenească" 432 | }, 433 | "mr": { 434 | "name": "Marathi", 435 | "native": "मराठी" 436 | }, 437 | "ms": { 438 | "name": "Malay", 439 | "native": "Bahasa Melayu" 440 | }, 441 | "mt": { 442 | "name": "Maltese", 443 | "native": "bil-Malti" 444 | }, 445 | "my": { 446 | "name": "Burmese", 447 | "native": "မြန်မာစာ" 448 | }, 449 | "na": { 450 | "name": "Nauruan", 451 | "native": "Dorerin Naoero" 452 | }, 453 | "nb": { 454 | "name": "Norwegian Bokmål", 455 | "native": "Norsk bokmål" 456 | }, 457 | "nd": { 458 | "name": "North Ndebele", 459 | "native": "Sindebele" 460 | }, 461 | "ne": { 462 | "name": "Nepali", 463 | "native": "नेपाली" 464 | }, 465 | "ng": { 466 | "name": "Ndonga", 467 | "native": "Oshiwambo" 468 | }, 469 | "nl": { 470 | "name": "Dutch", 471 | "native": "Nederlands" 472 | }, 473 | "nn": { 474 | "name": "Norwegian Nynorsk", 475 | "native": "Norsk nynorsk" 476 | }, 477 | "no": { 478 | "name": "Norwegian", 479 | "native": "Norsk" 480 | }, 481 | "nr": { 482 | "name": "South Ndebele", 483 | "native": "isiNdebele" 484 | }, 485 | "nv": { 486 | "name": "Navajo", 487 | "native": "Diné bizaad" 488 | }, 489 | "ny": { 490 | "name": "Chichewa", 491 | "native": "Chi-Chewa" 492 | }, 493 | "oc": { 494 | "name": "Occitan", 495 | "native": "Occitan" 496 | }, 497 | "oj": { 498 | "name": "Ojibwa", 499 | "native": "ᐊᓂᔑᓈᐯᒧᐎᓐ / Anishinaabemowin" 500 | }, 501 | "om": { 502 | "name": "Oromo", 503 | "native": "Oromoo" 504 | }, 505 | "or": { 506 | "name": "Oriya", 507 | "native": "ଓଡ଼ିଆ" 508 | }, 509 | "os": { 510 | "name": "Ossetian / Ossetic", 511 | "native": "Иронау" 512 | }, 513 | "pa": { 514 | "name": "Panjabi / Punjabi", 515 | "native": "ਪੰਜਾਬੀ / पंजाबी / پنجابي" 516 | }, 517 | "pi": { 518 | "name": "Pali", 519 | "native": "Pāli / पाऴि" 520 | }, 521 | "pl": { 522 | "name": "Polish", 523 | "native": "Polski" 524 | }, 525 | "ps": { 526 | "name": "Pashto", 527 | "native": "پښتو", 528 | "rtl": 1 529 | }, 530 | "pt": { 531 | "name": "Portuguese", 532 | "native": "Português" 533 | }, 534 | "qu": { 535 | "name": "Quechua", 536 | "native": "Runa Simi" 537 | }, 538 | "rm": { 539 | "name": "Raeto Romance", 540 | "native": "Rumantsch" 541 | }, 542 | "rn": { 543 | "name": "Kirundi", 544 | "native": "Kirundi" 545 | }, 546 | "ro": { 547 | "name": "Romanian", 548 | "native": "Română" 549 | }, 550 | "ru": { 551 | "name": "Russian", 552 | "native": "Русский" 553 | }, 554 | "rw": { 555 | "name": "Rwandi", 556 | "native": "Kinyarwandi" 557 | }, 558 | "sa": { 559 | "name": "Sanskrit", 560 | "native": "संस्कृतम्" 561 | }, 562 | "sc": { 563 | "name": "Sardinian", 564 | "native": "Sardu" 565 | }, 566 | "sd": { 567 | "name": "Sindhi", 568 | "native": "सिनधि" 569 | }, 570 | "se": { 571 | "name": "Northern Sami", 572 | "native": "Sámegiella" 573 | }, 574 | "sg": { 575 | "name": "Sango", 576 | "native": "Sängö" 577 | }, 578 | "sh": { 579 | "name": "Serbo-Croatian", 580 | "native": "Srpskohrvatski / Српскохрватски" 581 | }, 582 | "si": { 583 | "name": "Sinhalese", 584 | "native": "සිංහල" 585 | }, 586 | "sk": { 587 | "name": "Slovak", 588 | "native": "Slovenčina" 589 | }, 590 | "sl": { 591 | "name": "Slovenian", 592 | "native": "Slovenščina" 593 | }, 594 | "sm": { 595 | "name": "Samoan", 596 | "native": "Gagana Samoa" 597 | }, 598 | "sn": { 599 | "name": "Shona", 600 | "native": "chiShona" 601 | }, 602 | "so": { 603 | "name": "Somalia", 604 | "native": "Soomaaliga" 605 | }, 606 | "sq": { 607 | "name": "Albanian", 608 | "native": "Shqip" 609 | }, 610 | "sr": { 611 | "name": "Serbian", 612 | "native": "Српски" 613 | }, 614 | "ss": { 615 | "name": "Swati", 616 | "native": "SiSwati" 617 | }, 618 | "st": { 619 | "name": "Southern Sotho", 620 | "native": "Sesotho" 621 | }, 622 | "su": { 623 | "name": "Sundanese", 624 | "native": "Basa Sunda" 625 | }, 626 | "sv": { 627 | "name": "Swedish", 628 | "native": "Svenska" 629 | }, 630 | "sw": { 631 | "name": "Swahili", 632 | "native": "Kiswahili" 633 | }, 634 | "ta": { 635 | "name": "Tamil", 636 | "native": "தமிழ்" 637 | }, 638 | "te": { 639 | "name": "Telugu", 640 | "native": "తెలుగు" 641 | }, 642 | "tg": { 643 | "name": "Tajik", 644 | "native": "Тоҷикӣ" 645 | }, 646 | "th": { 647 | "name": "Thai", 648 | "native": "ไทย / Phasa Thai" 649 | }, 650 | "ti": { 651 | "name": "Tigrinya", 652 | "native": "ትግርኛ" 653 | }, 654 | "tk": { 655 | "name": "Turkmen", 656 | "native": "Туркмен / تركمن" 657 | }, 658 | "tl": { 659 | "name": "Tagalog / Filipino", 660 | "native": "Tagalog" 661 | }, 662 | "tn": { 663 | "name": "Tswana", 664 | "native": "Setswana" 665 | }, 666 | "to": { 667 | "name": "Tonga", 668 | "native": "Lea Faka-Tonga" 669 | }, 670 | "tr": { 671 | "name": "Turkish", 672 | "native": "Türkçe" 673 | }, 674 | "ts": { 675 | "name": "Tsonga", 676 | "native": "Xitsonga" 677 | }, 678 | "tt": { 679 | "name": "Tatar", 680 | "native": "Tatarça" 681 | }, 682 | "tw": { 683 | "name": "Twi", 684 | "native": "Twi" 685 | }, 686 | "ty": { 687 | "name": "Tahitian", 688 | "native": "Reo Mā`ohi" 689 | }, 690 | "ug": { 691 | "name": "Uyghur", 692 | "native": "Uyƣurqə / ئۇيغۇرچە" 693 | }, 694 | "uk": { 695 | "name": "Ukrainian", 696 | "native": "Українська" 697 | }, 698 | "ur": { 699 | "name": "Urdu", 700 | "native": "اردو", 701 | "rtl": 1 702 | }, 703 | "uz": { 704 | "name": "Uzbek", 705 | "native": "Ўзбек" 706 | }, 707 | "ve": { 708 | "name": "Venda", 709 | "native": "Tshivenḓa" 710 | }, 711 | "vi": { 712 | "name": "Vietnamese", 713 | "native": "Tiếng Việt" 714 | }, 715 | "vo": { 716 | "name": "Volapük", 717 | "native": "Volapük" 718 | }, 719 | "wa": { 720 | "name": "Walloon", 721 | "native": "Walon" 722 | }, 723 | "wo": { 724 | "name": "Wolof", 725 | "native": "Wollof" 726 | }, 727 | "xh": { 728 | "name": "Xhosa", 729 | "native": "isiXhosa" 730 | }, 731 | "yi": { 732 | "name": "Yiddish", 733 | "native": "ייִדיש", 734 | "rtl": 1 735 | }, 736 | "yo": { 737 | "name": "Yoruba", 738 | "native": "Yorùbá" 739 | }, 740 | "za": { 741 | "name": "Zhuang", 742 | "native": "Cuengh / Tôô / 壮语" 743 | }, 744 | "zh": { 745 | "name": "Chinese", 746 | "native": "中文" 747 | }, 748 | "zu": { 749 | "name": "Zulu", 750 | "native": "isiZulu" 751 | } 752 | } 753 | -------------------------------------------------------------------------------- /src/data/phones.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "manufacturer": "Xiaomi", 4 | "model": "M2010J19SG" 5 | }, 6 | { 7 | "manufacturer": "Xiaomi", 8 | "model": "POCO F1" 9 | }, 10 | { 11 | "manufacturer": "Xiaomi", 12 | "model": "Redmi 9A" 13 | }, 14 | { 15 | "manufacturer": "Xiaomi", 16 | "model": "Xiaomi Mi 4" 17 | }, 18 | { 19 | "manufacturer": "Xiaomi", 20 | "model": "Redmi Note 10 pro" 21 | }, 22 | { 23 | "manufacturer": "Xiaomi", 24 | "model": "Redmi Note 10" 25 | }, 26 | { 27 | "manufacturer": "Xiaomi", 28 | "model": "Xiaomi Redmi 1S" 29 | }, 30 | { 31 | "manufacturer": "Xiaomi", 32 | "model": "Xiaomi Mi 10T" 33 | }, 34 | { 35 | "manufacturer": "Xiaomi", 36 | "model": "Xiaomi Redmi 6 Pro" 37 | }, 38 | { 39 | "manufacturer": "Xiaomi", 40 | "model": "Xiaomi Redmi Y3" 41 | }, 42 | { 43 | "manufacturer": "Xiaomi", 44 | "model": "Xiaomi Redmi 9 Prime" 45 | }, 46 | { 47 | "manufacturer": "Xiaomi", 48 | "model": "Redmi Note 7" 49 | }, 50 | { 51 | "manufacturer": "Vivo", 52 | "model": "Vivo Y33s" 53 | }, 54 | { 55 | "manufacturer": "Vivo", 56 | "model": "Vivo V21 5G" 57 | }, 58 | { 59 | "manufacturer": "Vivo", 60 | "model": "Vivo Y20T" 61 | }, 62 | { 63 | "manufacturer": "Vivo", 64 | "model": "Vivo Y73 2021" 65 | }, 66 | { 67 | "manufacturer": "Vivo", 68 | "model": "Vivo X60" 69 | }, 70 | { 71 | "manufacturer": "Vivo", 72 | "model": "Vivo X70 Pro 5G" 73 | }, 74 | { 75 | "manufacturer": "Vivo", 76 | "model": "Vivo U3x" 77 | }, 78 | { 79 | "manufacturer": "Vivo", 80 | "model": "Vivo V20 Pro" 81 | }, 82 | { 83 | "manufacturer": "Vivo", 84 | "model": "Vivo Y21 2021" 85 | }, 86 | { 87 | "manufacturer": "Vivo", 88 | "model": "Vivo Y53s" 89 | }, 90 | { 91 | "manufacturer": "Vivo", 92 | "model": "Vivo S12 Pro" 93 | }, 94 | { 95 | "manufacturer": "Vivo", 96 | "model": "Vivo V21e 5G" 97 | }, 98 | { 99 | "manufacturer": "OnePlus", 100 | "model": "OnePlus Nord CE 5G" 101 | }, 102 | { 103 | "manufacturer": "OnePlus", 104 | "model": "OnePlus 9 Pro" 105 | }, 106 | { 107 | "manufacturer": "OnePlus", 108 | "model": "OnePlus 8T" 109 | }, 110 | { 111 | "manufacturer": "OnePlus", 112 | "model": "OnePlus 9" 113 | }, 114 | { 115 | "manufacturer": "OnePlus", 116 | "model": "OnePlus 7T" 117 | }, 118 | { 119 | "manufacturer": "OnePlus", 120 | "model": "OnePlus 6T" 121 | }, 122 | { 123 | "manufacturer": "OnePlus", 124 | "model": "OnePlus Nord 2" 125 | }, 126 | { 127 | "manufacturer": "OnePlus", 128 | "model": "OnePlus 7 Pro" 129 | }, 130 | { 131 | "manufacturer": "OnePlus", 132 | "model": "OnePlus Nord" 133 | }, 134 | { 135 | "manufacturer": "Realme", 136 | "model": "RMX2185" 137 | }, 138 | { 139 | "manufacturer": "Realme", 140 | "model": "Realme GT Neo2 5G" 141 | }, 142 | { 143 | "manufacturer": "Realme", 144 | "model": "Realme 8 5G" 145 | }, 146 | { 147 | "manufacturer": "Realme", 148 | "model": "Realme C11 2021" 149 | }, 150 | { 151 | "manufacturer": "Realme", 152 | "model": "Realme GT" 153 | }, 154 | { 155 | "manufacturer": "Realme", 156 | "model": "Realme Narzo 30" 157 | }, 158 | { 159 | "manufacturer": "Realme", 160 | "model": "Realme Q3i 5G" 161 | }, 162 | { 163 | "manufacturer": "Realme", 164 | "model": "Realme 8s 5G" 165 | }, 166 | { 167 | "manufacturer": "Realme", 168 | "model": "Realme 8i" 169 | }, 170 | { 171 | "manufacturer": "Realme", 172 | "model": "Realme Narzo 50A" 173 | }, 174 | { 175 | "manufacturer": "Realme", 176 | "model": "Realme C21Y" 177 | }, 178 | { 179 | "manufacturer": "Oppo", 180 | "model": "OPPO A55" 181 | }, 182 | { 183 | "manufacturer": "Oppo", 184 | "model": "OPPO A74 5G" 185 | }, 186 | { 187 | "manufacturer": "Oppo", 188 | "model": "OPPO A53" 189 | }, 190 | { 191 | "manufacturer": "Oppo", 192 | "model": "OPPO A31" 193 | }, 194 | { 195 | "manufacturer": "Oppo", 196 | "model": "OPPO A12" 197 | }, 198 | { 199 | "manufacturer": "Oppo", 200 | "model": "OPPO Reno6 Pro" 201 | }, 202 | { 203 | "manufacturer": "Oppo", 204 | "model": "OPPO Reno6" 205 | }, 206 | { 207 | "manufacturer": "Oppo", 208 | "model": "OPPO F19 Pro" 209 | }, 210 | { 211 | "manufacturer": "Oppo", 212 | "model": "OPPO F19s" 213 | }, 214 | { 215 | "manufacturer": "Oppo", 216 | "model": "Oppo F19 Pro+" 217 | }, 218 | { 219 | "manufacturer": "Oppo", 220 | "model": "Oppo A33" 221 | }, 222 | { 223 | "manufacturer": "Oppo", 224 | "model": "Oppo Reno 3 Pro" 225 | }, 226 | { 227 | "manufacturer": "Oppo", 228 | "model": "Oppo Reno 4 Pro" 229 | }, 230 | { 231 | "manufacturer": "Oppo", 232 | "model": "Oppo Find X2" 233 | }, 234 | { 235 | "manufacturer": "Oppo", 236 | "model": "OPPO F15" 237 | }, 238 | { 239 | "manufacturer": "Oppo", 240 | "model": "OPPO Reno 2F" 241 | }, 242 | { 243 | "manufacturer": "Oppo", 244 | "model": "OPPO K3" 245 | }, 246 | { 247 | "manufacturer": "Oppo", 248 | "model": "OPPO A9" 249 | }, 250 | { 251 | "manufacturer": "Oppo", 252 | "model": "OPPO A1k" 253 | }, 254 | { 255 | "manufacturer": "Oppo", 256 | "model": "OPPO A5s" 257 | }, 258 | { 259 | "manufacturer": "Samsung", 260 | "model": "Samsung Galaxy M31s" 261 | }, 262 | { 263 | "manufacturer": "Samsung", 264 | "model": "Samsung Galaxy M32" 265 | }, 266 | { 267 | "manufacturer": "Samsung", 268 | "model": "Samsung Galaxy F62" 269 | }, 270 | { 271 | "manufacturer": "Samsung", 272 | "model": "Samsung Galaxy M52 5G" 273 | }, 274 | { 275 | "manufacturer": "Samsung", 276 | "model": "Samsung Galaxy M12" 277 | }, 278 | { 279 | "manufacturer": "Samsung", 280 | "model": "Samsung Galaxy M51" 281 | }, 282 | { 283 | "manufacturer": "Samsung", 284 | "model": "Samsung Galaxy F12" 285 | }, 286 | { 287 | "manufacturer": "Samsung", 288 | "model": "Samsung Galaxy F22" 289 | }, 290 | { 291 | "manufacturer": "Samsung", 292 | "model": "Samsung Galaxy A52" 293 | }, 294 | { 295 | "manufacturer": "Samsung", 296 | "model": "Samsung Galaxy S20 FE 5G" 297 | }, 298 | { 299 | "manufacturer": "Samsung", 300 | "model": "Samsung Galaxy M52" 301 | }, 302 | { 303 | "manufacturer": "Samsung", 304 | "model": "Samsung Galaxy M62" 305 | }, 306 | { 307 | "manufacturer": "Samsung", 308 | "model": "Samsung Galaxy S21 Ultra" 309 | }, 310 | { 311 | "manufacturer": "Samsung", 312 | "model": "Samsung Galaxy A52s 5G" 313 | }, 314 | { 315 | "manufacturer": "Samsung", 316 | "model": "Samsung Galaxy S21" 317 | }, 318 | { 319 | "manufacturer": "Samsung", 320 | "model": "Samsung Galaxy M21 2021" 321 | }, 322 | { 323 | "manufacturer": "Samsung", 324 | "model": "Samsung Galaxy F42" 325 | }, 326 | { 327 | "manufacturer": "Samsung", 328 | "model": "Samsung Galaxy A12" 329 | }, 330 | { 331 | "manufacturer": "Samsung", 332 | "model": "Samsung Galaxy F41" 333 | }, 334 | { 335 | "manufacturer": "Samsung", 336 | "model": "Samsung Galaxy M01 Core" 337 | } 338 | ] 339 | -------------------------------------------------------------------------------- /src/data/phones.ts: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 Emmadi Sumith Kumar 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | const phones_list = [ 24 | { 25 | manufacturer: "Xiaomi", 26 | model: "M2010J19SG", 27 | }, 28 | { 29 | manufacturer: "Xiaomi", 30 | model: "POCO F1", 31 | }, 32 | { 33 | manufacturer: "Xiaomi", 34 | model: "Redmi 9A", 35 | }, 36 | { 37 | manufacturer: "Xiaomi", 38 | model: "Xiaomi Mi 4", 39 | }, 40 | { 41 | manufacturer: "Xiaomi", 42 | model: "Redmi Note 10 pro", 43 | }, 44 | { 45 | manufacturer: "Xiaomi", 46 | model: "Redmi Note 10", 47 | }, 48 | { 49 | manufacturer: "Xiaomi", 50 | model: "Xiaomi Redmi 1S", 51 | }, 52 | { 53 | manufacturer: "Xiaomi", 54 | model: "Xiaomi Mi 10T", 55 | }, 56 | { 57 | manufacturer: "Xiaomi", 58 | model: "Xiaomi Redmi 6 Pro", 59 | }, 60 | { 61 | manufacturer: "Xiaomi", 62 | model: "Xiaomi Redmi Y3", 63 | }, 64 | { 65 | manufacturer: "Xiaomi", 66 | model: "Xiaomi Redmi 9 Prime", 67 | }, 68 | { 69 | manufacturer: "Xiaomi", 70 | model: "Redmi Note 7", 71 | }, 72 | { 73 | manufacturer: "Vivo", 74 | model: "Vivo Y33s", 75 | }, 76 | { 77 | manufacturer: "Vivo", 78 | model: "Vivo V21 5G", 79 | }, 80 | { 81 | manufacturer: "Vivo", 82 | model: "Vivo Y20T", 83 | }, 84 | { 85 | manufacturer: "Vivo", 86 | model: "Vivo Y73 2021", 87 | }, 88 | { 89 | manufacturer: "Vivo", 90 | model: "Vivo X60", 91 | }, 92 | { 93 | manufacturer: "Vivo", 94 | model: "Vivo X70 Pro 5G", 95 | }, 96 | { 97 | manufacturer: "Vivo", 98 | model: "Vivo U3x", 99 | }, 100 | { 101 | manufacturer: "Vivo", 102 | model: "Vivo V20 Pro", 103 | }, 104 | { 105 | manufacturer: "Vivo", 106 | model: "Vivo Y21 2021", 107 | }, 108 | { 109 | manufacturer: "Vivo", 110 | model: "Vivo Y53s", 111 | }, 112 | { 113 | manufacturer: "Vivo", 114 | model: "Vivo S12 Pro", 115 | }, 116 | { 117 | manufacturer: "Vivo", 118 | model: "Vivo V21e 5G", 119 | }, 120 | { 121 | manufacturer: "OnePlus", 122 | model: "OnePlus Nord CE 5G", 123 | }, 124 | { 125 | manufacturer: "OnePlus", 126 | model: "OnePlus 9 Pro", 127 | }, 128 | { 129 | manufacturer: "OnePlus", 130 | model: "OnePlus 8T", 131 | }, 132 | { 133 | manufacturer: "OnePlus", 134 | model: "OnePlus 9", 135 | }, 136 | { 137 | manufacturer: "OnePlus", 138 | model: "OnePlus 7T", 139 | }, 140 | { 141 | manufacturer: "OnePlus", 142 | model: "OnePlus 6T", 143 | }, 144 | { 145 | manufacturer: "OnePlus", 146 | model: "OnePlus Nord 2", 147 | }, 148 | { 149 | manufacturer: "OnePlus", 150 | model: "OnePlus 7 Pro", 151 | }, 152 | { 153 | manufacturer: "OnePlus", 154 | model: "OnePlus Nord", 155 | }, 156 | { 157 | manufacturer: "Realme", 158 | model: "RMX2185", 159 | }, 160 | { 161 | manufacturer: "Realme", 162 | model: "Realme GT Neo2 5G", 163 | }, 164 | { 165 | manufacturer: "Realme", 166 | model: "Realme 8 5G", 167 | }, 168 | { 169 | manufacturer: "Realme", 170 | model: "Realme C11 2021", 171 | }, 172 | { 173 | manufacturer: "Realme", 174 | model: "Realme GT", 175 | }, 176 | { 177 | manufacturer: "Realme", 178 | model: "Realme Narzo 30", 179 | }, 180 | { 181 | manufacturer: "Realme", 182 | model: "Realme Q3i 5G", 183 | }, 184 | { 185 | manufacturer: "Realme", 186 | model: "Realme 8s 5G", 187 | }, 188 | { 189 | manufacturer: "Realme", 190 | model: "Realme 8i", 191 | }, 192 | { 193 | manufacturer: "Realme", 194 | model: "Realme Narzo 50A", 195 | }, 196 | { 197 | manufacturer: "Realme", 198 | model: "Realme C21Y", 199 | }, 200 | { 201 | manufacturer: "Oppo", 202 | model: "OPPO A55", 203 | }, 204 | { 205 | manufacturer: "Oppo", 206 | model: "OPPO A74 5G", 207 | }, 208 | { 209 | manufacturer: "Oppo", 210 | model: "OPPO A53", 211 | }, 212 | { 213 | manufacturer: "Oppo", 214 | model: "OPPO A31", 215 | }, 216 | { 217 | manufacturer: "Oppo", 218 | model: "OPPO A12", 219 | }, 220 | { 221 | manufacturer: "Oppo", 222 | model: "OPPO Reno6 Pro", 223 | }, 224 | { 225 | manufacturer: "Oppo", 226 | model: "OPPO Reno6", 227 | }, 228 | { 229 | manufacturer: "Oppo", 230 | model: "OPPO F19 Pro", 231 | }, 232 | { 233 | manufacturer: "Oppo", 234 | model: "OPPO F19s", 235 | }, 236 | { 237 | manufacturer: "Oppo", 238 | model: "Oppo F19 Pro+", 239 | }, 240 | { 241 | manufacturer: "Oppo", 242 | model: "Oppo A33", 243 | }, 244 | { 245 | manufacturer: "Oppo", 246 | model: "Oppo Reno 3 Pro", 247 | }, 248 | { 249 | manufacturer: "Oppo", 250 | model: "Oppo Reno 4 Pro", 251 | }, 252 | { 253 | manufacturer: "Oppo", 254 | model: "Oppo Find X2", 255 | }, 256 | { 257 | manufacturer: "Oppo", 258 | model: "OPPO F15", 259 | }, 260 | { 261 | manufacturer: "Oppo", 262 | model: "OPPO Reno 2F", 263 | }, 264 | { 265 | manufacturer: "Oppo", 266 | model: "OPPO K3", 267 | }, 268 | { 269 | manufacturer: "Oppo", 270 | model: "OPPO A9", 271 | }, 272 | { 273 | manufacturer: "Oppo", 274 | model: "OPPO A1k", 275 | }, 276 | { 277 | manufacturer: "Oppo", 278 | model: "OPPO A5s", 279 | }, 280 | { 281 | manufacturer: "Samsung", 282 | model: "Samsung Galaxy M31s", 283 | }, 284 | { 285 | manufacturer: "Samsung", 286 | model: "Samsung Galaxy M32", 287 | }, 288 | { 289 | manufacturer: "Samsung", 290 | model: "Samsung Galaxy F62", 291 | }, 292 | { 293 | manufacturer: "Samsung", 294 | model: "Samsung Galaxy M52 5G", 295 | }, 296 | { 297 | manufacturer: "Samsung", 298 | model: "Samsung Galaxy M12", 299 | }, 300 | { 301 | manufacturer: "Samsung", 302 | model: "Samsung Galaxy M51", 303 | }, 304 | { 305 | manufacturer: "Samsung", 306 | model: "Samsung Galaxy F12", 307 | }, 308 | { 309 | manufacturer: "Samsung", 310 | model: "Samsung Galaxy F22", 311 | }, 312 | { 313 | manufacturer: "Samsung", 314 | model: "Samsung Galaxy A52", 315 | }, 316 | { 317 | manufacturer: "Samsung", 318 | model: "Samsung Galaxy S20 FE 5G", 319 | }, 320 | { 321 | manufacturer: "Samsung", 322 | model: "Samsung Galaxy M52", 323 | }, 324 | { 325 | manufacturer: "Samsung", 326 | model: "Samsung Galaxy M62", 327 | }, 328 | { 329 | manufacturer: "Samsung", 330 | model: "Samsung Galaxy S21 Ultra", 331 | }, 332 | { 333 | manufacturer: "Samsung", 334 | model: "Samsung Galaxy A52s 5G", 335 | }, 336 | { 337 | manufacturer: "Samsung", 338 | model: "Samsung Galaxy S21", 339 | }, 340 | { 341 | manufacturer: "Samsung", 342 | model: "Samsung Galaxy M21 2021", 343 | }, 344 | { 345 | manufacturer: "Samsung", 346 | model: "Samsung Galaxy F42", 347 | }, 348 | { 349 | manufacturer: "Samsung", 350 | model: "Samsung Galaxy A12", 351 | }, 352 | { 353 | manufacturer: "Samsung", 354 | model: "Samsung Galaxy F41", 355 | }, 356 | { 357 | manufacturer: "Samsung", 358 | model: "Samsung Galaxy M01 Core", 359 | }, 360 | ]; 361 | 362 | const getRandomDevice = (): { manufacturer: string; model: string } => { 363 | const randomIndex = Math.floor(Math.random() * phones_list.length); 364 | return phones_list[randomIndex]; 365 | }; 366 | 367 | const device = getRandomDevice(); 368 | 369 | export { device }; 370 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 Emmadi Sumith Kumar 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import { login as loginFunction } from "./login.js"; 24 | import { verifyOtp as verifyOtpFunction } from "./verifyOtp.js"; 25 | import { 26 | search as searchFunction, 27 | bulkSearch as bulkSearchFunction, 28 | } from "./search.js"; 29 | 30 | export const login = loginFunction; 31 | export const verifyOtp = verifyOtpFunction; 32 | export const search = searchFunction; 33 | export const bulkSearch = bulkSearchFunction; 34 | 35 | const truecallerjs = { 36 | login, 37 | verifyOtp, 38 | search, 39 | bulkSearch, 40 | }; 41 | 42 | export default truecallerjs; 43 | -------------------------------------------------------------------------------- /src/json-to-pretty-yaml.d.ts: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 Emmadi Sumith Kumar 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | declare module "json-to-pretty-yaml" { 24 | export function stringify(obj: unknown, color?: boolean): string; 25 | } 26 | -------------------------------------------------------------------------------- /src/login.ts: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 Emmadi Sumith Kumar 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import axios from "axios"; 24 | import { parsePhoneNumber } from "awesome-phonenumber"; 25 | import { device } from "./data/phones.js"; 26 | 27 | interface LoginResponse { 28 | status: number; 29 | message: string; 30 | domain: string; 31 | parsedPhoneNumber: number; 32 | parsedCountryCode: string; 33 | requestId: string; 34 | method: string; 35 | tokenTtl: number; 36 | } 37 | 38 | function generateRandomString(length: number): string { 39 | let result = ""; 40 | const characters = "abcdefghijklmnopqrstuvwxyz0123456789"; 41 | const charactersLength = characters.length; 42 | 43 | for (let i = 0; i < length; i++) { 44 | result += characters.charAt(Math.floor(Math.random() * charactersLength)); 45 | } 46 | 47 | return result; 48 | } 49 | 50 | /** 51 | * Login to Truecaller. 52 | * 53 | * @param {string} phoneNumber - Phone number in international format. 54 | * @returns {Promise} - Promise that resolves to the login response containing the requestId used for OTP verification. 55 | */ 56 | async function login(phoneNumber: string): Promise { 57 | const pn = parsePhoneNumber(phoneNumber); 58 | 59 | if (!pn?.valid) { 60 | throw new Error("Invalid phone number."); 61 | } 62 | 63 | const postUrl = 64 | "https://account-asia-south1.truecaller.com/v2/sendOnboardingOtp"; 65 | 66 | const data = { 67 | countryCode: pn.regionCode, 68 | dialingCode: pn.countryCode, 69 | installationDetails: { 70 | app: { 71 | buildVersion: 5, 72 | majorVersion: 11, 73 | minorVersion: 7, 74 | store: "GOOGLE_PLAY", 75 | }, 76 | device: { 77 | deviceId: generateRandomString(16), 78 | language: "en", 79 | manufacturer: device.manufacturer, 80 | model: device.model, 81 | osName: "Android", 82 | osVersion: "10", 83 | mobileServices: ["GMS"], 84 | }, 85 | language: "en", 86 | }, 87 | phoneNumber: pn.number.significant, 88 | region: "region-2", 89 | sequenceNo: 2, 90 | }; 91 | 92 | const options = { 93 | method: "POST", 94 | headers: { 95 | "content-type": "application/json; charset=UTF-8", 96 | "accept-encoding": "gzip", 97 | "user-agent": "Truecaller/11.75.5 (Android;10)", 98 | clientsecret: "lvc22mp3l1sfv6ujg83rd17btt", 99 | }, 100 | url: postUrl, 101 | data, 102 | }; 103 | 104 | const res = await axios(options); 105 | return res.data; 106 | } 107 | 108 | export { login }; 109 | -------------------------------------------------------------------------------- /src/search.ts: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 Emmadi Sumith Kumar 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import axios, { AxiosResponse } from "axios"; 24 | import { parsePhoneNumber } from "awesome-phonenumber"; 25 | import { Builder } from "xml2js"; 26 | import { jsonToPlainText } from "json-to-plain-text"; 27 | import { stringify as yamlStringify } from "json-to-pretty-yaml"; 28 | import { countries } from "./data/countries.js"; 29 | 30 | interface Address { 31 | city: string; 32 | countryCode: string; 33 | timeZone: string; 34 | type: string; 35 | } 36 | 37 | interface InternetAddress { 38 | id: string; 39 | service: string; 40 | caption: string; 41 | type: string; 42 | } 43 | 44 | interface CountryDetails { 45 | name: string; 46 | native: string; 47 | phone: number[]; 48 | continent: string; 49 | capital: string; 50 | currency: string[]; 51 | languages: string[]; 52 | flag: string; 53 | flagURL: string; 54 | } 55 | 56 | interface Data { 57 | name?: string; 58 | altName?: string; 59 | addresses?: Address[]; 60 | internetAddresses?: InternetAddress[]; 61 | } 62 | 63 | interface SearchData { 64 | number: string; 65 | countryCode: string; 66 | installationId: string; 67 | } 68 | 69 | interface BulkSearchData { 70 | data: Data[]; 71 | } 72 | 73 | class Format { 74 | private data: BulkSearchData; 75 | 76 | constructor(data: BulkSearchData) { 77 | this.data = data; 78 | } 79 | 80 | public json(): BulkSearchData { 81 | return this.data; 82 | } 83 | 84 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 85 | public xml(color = false): string { 86 | const builder = new Builder(); 87 | const xml = builder.buildObject(JSON.parse(JSON.stringify(this.json()))); 88 | return xml; 89 | } 90 | 91 | public yaml(color = false): string { 92 | return yamlStringify(JSON.parse(JSON.stringify(this.json())), color); 93 | } 94 | 95 | public text(color = false, space = false): string { 96 | const options = { 97 | color: color, // Whether to apply colors to the output or not 98 | spacing: space, // Whether to include spacing after colons or not 99 | squareBracketsForArray: false, // Whether to use square brackets for arrays or not 100 | doubleQuotesForKeys: false, // Whether to use double quotes for object keys or not 101 | doubleQuotesForValues: false, 102 | }; 103 | return jsonToPlainText(JSON.parse(JSON.stringify(this.json())), options); 104 | } 105 | 106 | public getName(): string { 107 | return this.json()?.data[0]?.name || "unknown name"; 108 | } 109 | 110 | public getAlternateName(): string { 111 | return this.json()?.data[0]?.altName || "no alternate name"; 112 | } 113 | 114 | public getAddresses(): Address[] { 115 | return this.json()?.data[0]?.addresses || []; 116 | } 117 | 118 | public getEmailId(): string { 119 | const data = this.json()?.data; 120 | if (data && data.length > 0) { 121 | const internetAddresses = data[0]?.internetAddresses; 122 | if (internetAddresses && internetAddresses.length > 0) { 123 | const id = internetAddresses[0]?.id; 124 | if (id) { 125 | return id; 126 | } 127 | } 128 | } 129 | return "unknown email"; 130 | } 131 | 132 | public getCountryDetails(): CountryDetails { 133 | const data = this.json()?.data; 134 | if (data && data.length > 0) { 135 | const addresses = data[0]?.addresses; 136 | if (addresses && addresses.length > 0) { 137 | const countryCode = addresses[0]?.countryCode; 138 | if (countryCode) { 139 | return countries[countryCode]; 140 | } 141 | } 142 | } 143 | return { 144 | name: "unknown", 145 | native: "unknwon", 146 | phone: [], 147 | continent: "unknwon", 148 | capital: "unknwon", 149 | currency: ["unknwon"], 150 | languages: ["unknwon"], 151 | flag: "🇦🇩", 152 | flagURL: "unknwon", 153 | }; 154 | } 155 | } 156 | 157 | /** 158 | * Searching phone number on truecallerjs 159 | * @var response => {...} 160 | * @method response.json(color) JSON response. 161 | * @method response.xml(color) XML output. 162 | * @method response.yaml(color) YAML output. 163 | * @method response.html(color) HTML output. 164 | * @method response.text(color,space) JSON response. 165 | * @method response.getName() => "Sumith Emmadi" 166 | * @method response.getAlternateName() => "sumith" 167 | * @method response.getAddresses() => {....} 168 | * @method response.getEmailId() => sumithemmadi244@gmail.com 169 | * @method response.getCountryDetails() => {...} 170 | * @name search 171 | * @function truecallerjs.search(search_data) 172 | * @return {Object} It contains details of the phone number 173 | */ 174 | function search(searchData: SearchData): Promise { 175 | const phoneNumber = parsePhoneNumber(searchData.number, { 176 | regionCode: searchData.countryCode, 177 | }); 178 | const significantNumber = phoneNumber?.number?.significant; 179 | 180 | return axios 181 | .get(`https://search5-noneu.truecaller.com/v2/search`, { 182 | params: { 183 | q: significantNumber, 184 | countryCode: phoneNumber.regionCode, 185 | type: 4, 186 | locAddr: "", 187 | placement: "SEARCHRESULTS,HISTORY,DETAILS", 188 | encoding: "json", 189 | }, 190 | headers: { 191 | "content-type": "application/json; charset=UTF-8", 192 | "accept-encoding": "gzip", 193 | "user-agent": "Truecaller/11.75.5 (Android;10)", 194 | Authorization: `Bearer ${searchData.installationId}`, 195 | }, 196 | }) 197 | .then( 198 | (response: AxiosResponse) => { 199 | // console.log(response); 200 | return new Format(response.data); 201 | }, 202 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 203 | (error: any) => { 204 | return new Format(error); 205 | }, 206 | ); 207 | } 208 | 209 | /** 210 | * Bulk search on truecallerjs 211 | * @name bulkSearch 212 | * @function truecallerjs.bulkSearch(phoneNumbers,countryCode,installationId) 213 | * @param {String} phoneNumbers phone number separted with coma. 214 | * @param {String} installationId 6-digits OTP . 215 | * @return {Object} It contains phone numbers information in a array 216 | */ 217 | function bulkSearch( 218 | phoneNumbers: string, 219 | regionCode: string, 220 | installationId: string, 221 | ): Promise { 222 | return axios 223 | .get(`https://search5-noneu.truecaller.com/v2/bulk`, { 224 | params: { 225 | q: phoneNumbers, 226 | countryCode: regionCode, 227 | type: 14, 228 | placement: "SEARCHRESULTS,HISTORY,DETAILS", 229 | encoding: "json", 230 | }, 231 | headers: { 232 | "content-type": "application/json; charset=UTF-8", 233 | "accept-encoding": "gzip", 234 | "user-agent": "Truecaller/11.75.5 (Android;10)", 235 | Authorization: `Bearer ${installationId}`, 236 | }, 237 | }) 238 | .then( 239 | (response: AxiosResponse) => { 240 | return response.data; 241 | }, 242 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 243 | (error: any) => { 244 | return JSON.parse(JSON.stringify(error)); 245 | }, 246 | ); 247 | } 248 | 249 | export { search, bulkSearch }; 250 | -------------------------------------------------------------------------------- /src/verifyOtp.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | // MIT License 3 | 4 | // Copyright (c) 2021 Emmadi Sumith Kumar 5 | 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | import { parsePhoneNumber } from "awesome-phonenumber"; 25 | import axios, { AxiosRequestConfig } from "axios"; 26 | 27 | /** 28 | * Verifying mobile number with OTP 29 | * 30 | * @name truecallerjs.verifyOtp 31 | * @function verifyOtp 32 | * @param {string} phonenumber - Phone number in international format. 33 | * @param {Object} json_data - JSON response of the login(phonenumber) function. 34 | * @param {string} otp - 6-digit OTP. 35 | * @returns {Promise} - JSON output containing the installationId. 36 | * 37 | * Follow this documentation for more details: https://github.com/sumithemmadi/truecallerjs/tree/main/docs 38 | */ 39 | async function verifyOtp( 40 | phonenumber: string, 41 | json_data: any, 42 | otp: string, 43 | ): Promise { 44 | const pn = parsePhoneNumber(phonenumber); 45 | if (!pn.valid) { 46 | throw new Error("Phone number should be in international format."); 47 | } 48 | const postData = { 49 | countryCode: pn.regionCode, 50 | dialingCode: pn.countryCode, 51 | phoneNumber: pn.number.significant, 52 | requestId: json_data.requestId, 53 | token: otp, 54 | }; 55 | 56 | const options: AxiosRequestConfig = { 57 | method: "POST", 58 | headers: { 59 | "content-type": "application/json; charset=UTF-8", 60 | "accept-encoding": "gzip", 61 | "user-agent": "Truecaller/11.75.5 (Android;10)", 62 | clientsecret: "lvc22mp3l1sfv6ujg83rd17btt", 63 | }, 64 | url: "https://account-asia-south1.truecaller.com/v1/verifyOnboardingOtp", 65 | data: postData, 66 | }; 67 | 68 | const res = await axios(options); 69 | return res.data; 70 | } 71 | 72 | export { verifyOtp }; 73 | -------------------------------------------------------------------------------- /test/1-login.test.js: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 Emmadi Sumith Kumar 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | // import truecallerjs from "../dist/index.js"; 24 | 25 | // 1-login.test.js 26 | 27 | import { login } from "../dist/index.js"; 28 | 29 | describe("Login Tests", () => { 30 | test("should perform login", async () => { 31 | const phoneNumber = process.env.TEST_PHONE_NUMBER || "+919912345678"; 32 | const result = await login(phoneNumber); 33 | // console.log(result); 34 | expect(result.status).toBeDefined(); 35 | expect(result.message).toBeDefined(); 36 | expect(result.parsedPhoneNumber).toBeDefined(); 37 | expect(result.parsedCountryCode).toBeDefined(); 38 | expect(result.requestId).toBeDefined(); 39 | expect(result.method).toBeDefined(); 40 | expect(result.tokenTtl).toBeDefined(); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /test/2-verifyOtp.test.js: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 Emmadi Sumith Kumar 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import { login, verifyOtp } from "../dist/index.js"; 24 | 25 | describe("Verify Otp", () => { 26 | test("Should verify otp", async () => { 27 | const phoneNumber = process.env.TEST_PHONE_NUMBER || "+919912345678"; 28 | const result = await login(phoneNumber); 29 | 30 | var data = await verifyOtp(phoneNumber, result, "123456"); 31 | console.log(data); 32 | expect(data).toBeDefined(); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /test/3-search.test.js: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 Emmadi Sumith Kumar 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import { search } from "../dist/search.js"; 24 | 25 | describe("Search a phone number", () => { 26 | test("Should search for a phone number details", async () => { 27 | var search_data = { 28 | number: process.env.TEST_PHONE_NUMBER || "9912345678", 29 | countryCode: "IN", // Country code to use by default if phone number is not in `e164` format(Internation format) 30 | installationId: 31 | process.env.TEST_INSTALLATION_ID || 32 | "a1k07--Vgdfyvv_rftf5uuudhuhnkljyvvtfftjuhbuijbhug", 33 | }; 34 | var response = await search(search_data); 35 | console.log(response); 36 | 37 | expect(response).toBeDefined(); 38 | expect(response.data).toBeDefined(); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/4-bulkSearch.test.js: -------------------------------------------------------------------------------- 1 | // MIT License 2 | 3 | // Copyright (c) 2021 Emmadi Sumith Kumar 4 | 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | 12 | // The above copyright notice and this permission notice shall be included in all 13 | // copies or substantial portions of the Software. 14 | 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | // SOFTWARE. 22 | 23 | import { bulkSearch } from "../dist/search.js"; 24 | 25 | describe("Bulk search a phone number", () => { 26 | test("Should bulk search list of phone numbers and with there details", async () => { 27 | var countryCode = "IN"; 28 | var installationId = "a1k07--Vgdfyvv_rftf5uuudhuhnkljyvvtfftjuhbuijbhug"; 29 | var phoneNumbers = "9912345678,+14051234567,+919987654321"; // Phone numbers seperated by comma's 30 | 31 | var response = await bulkSearch(phoneNumbers, countryCode, installationId); 32 | console.log(response); 33 | expect(response).toBeDefined(); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "esnext", 4 | "target": "esnext", 5 | "outDir": "dist", 6 | 7 | // "target": "es2016", 8 | // "module": "commonjs", 9 | // "outDir": "dist/cjs", 10 | 11 | "rootDir": "src", 12 | "baseUrl": "src", 13 | "allowJs": true, 14 | "allowSyntheticDefaultImports": true, 15 | "esModuleInterop": true, 16 | "listEmittedFiles": false, 17 | "listFiles": false, 18 | "moduleResolution": "node", 19 | "pretty": true, 20 | "resolveJsonModule": true, 21 | "sourceMap": false, 22 | "declaration": true, 23 | "declarationMap": false, 24 | "forceConsistentCasingInFileNames": true, 25 | "strict": true, 26 | "skipLibCheck": true, 27 | "typeRoots": ["./node_modules/@types", "./typings/"], 28 | "types": ["node"] 29 | }, 30 | "compileOnSave": true, 31 | "include": ["src/**/*.ts", "typings/index.d.ts"], 32 | "exclude": ["node_modules", "dist"] 33 | } 34 | -------------------------------------------------------------------------------- /typings/index.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace truecallerjs { 2 | /** 3 | * Response object returned by the login function. 4 | */ 5 | interface LoginResponse { 6 | status: number; 7 | message: string; 8 | domain: string; 9 | parsedPhoneNumber: number; 10 | parsedCountryCode: string; 11 | requestId: string; 12 | method: string; 13 | tokenTtl: number; 14 | } 15 | 16 | /** 17 | * Logs in to Truecaller. 18 | * 19 | * @param phoneNumber - Phone number in international format. 20 | * @returns A Promise that resolves to the login response containing the requestId used for OTP verification. 21 | */ 22 | function login(phoneNumber: string): Promise; 23 | 24 | /** 25 | * Verifies a mobile number with OTP. 26 | * 27 | * @param phoneNumber - Phone number in international format. 28 | * @param jsonData - JSON response of the login function. 29 | * @param otp - 6-digit OTP. 30 | * @returns A Promise that resolves to a JSON object containing the installationId. 31 | */ 32 | function verifyOtp( 33 | phoneNumber: string, 34 | jsonData: LoginResponse, 35 | otp: string, 36 | ): Promise; 37 | 38 | /** 39 | * Address details. 40 | */ 41 | interface Address { 42 | city: string; 43 | countryCode: string; 44 | timeZone: string; 45 | type: string; 46 | } 47 | 48 | /** 49 | * Internet address details. 50 | */ 51 | interface InternetAddress { 52 | id: string; 53 | service: string; 54 | caption: string; 55 | type: string; 56 | } 57 | 58 | /** 59 | * Country details. 60 | */ 61 | interface CountryDetails { 62 | name: string; 63 | native: string; 64 | phone: number[]; 65 | continent: string; 66 | capital: string; 67 | currency: string[]; 68 | languages: string[]; 69 | flag: string; 70 | flagURL: string; 71 | } 72 | 73 | /** 74 | * Data object containing information about a phone number. 75 | */ 76 | interface Data { 77 | name?: string; 78 | altName?: string; 79 | addresses?: Address[]; 80 | internetAddresses?: InternetAddress[]; 81 | } 82 | 83 | /** 84 | * Search data object used for searching a phone number. 85 | */ 86 | interface SearchData { 87 | number: string; 88 | countryCode: string; 89 | installationId: string; 90 | } 91 | 92 | /** 93 | * Response data object containing an array of Data objects. 94 | */ 95 | interface BulkSearchData { 96 | data: Data[]; 97 | } 98 | 99 | /** 100 | * Format class for formatting response data. 101 | */ 102 | class Format { 103 | constructor(data: BulkSearchData); 104 | json(color?: boolean): BulkSearchData; 105 | xml(color?: boolean): string; 106 | yaml(color?: boolean): string; 107 | text(color?: boolean, space?: boolean): string; 108 | getName(): string; 109 | getAlternateName(): string; 110 | getAddresses(): Address[]; 111 | getEmailId(): string; 112 | getCountryDetails(): CountryDetails; 113 | } 114 | 115 | /** 116 | * Searches for a phone number on Truecaller. 117 | * 118 | * @param searchData - Search data object containing the number, countryCode, and installationId. 119 | * @returns A Promise that resolves to a Format object containing details of the phone number. 120 | */ 121 | function search(searchData: SearchData): Promise; 122 | 123 | /** 124 | * Performs bulk search for multiple phone numbers on Truecaller. 125 | * 126 | * @param phoneNumbers - Phone numbers separated by commas. 127 | * @param countryCode - Country code to use by default if any phone number is not in E.164 format (international format). 128 | * @param installationId - 6-digit OTP. 129 | * @returns A Promise that resolves to a BulkSearchData object containing phone number information in an array. 130 | */ 131 | function bulkSearch( 132 | phoneNumbers: string, 133 | countryCode: string, 134 | installationId: string, 135 | ): Promise; 136 | } 137 | 138 | export = truecallerjs; 139 | --------------------------------------------------------------------------------