├── .eslintrc.js
├── .github
├── CODE_OF_CONDUCT.md
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── ask.md
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ └── greetings.yml
├── .gitignore
├── LICENSE
├── README.md
├── config.json
├── database
├── bot
│ ├── banned.json
│ ├── mute.json
│ ├── premium.json
│ ├── registered.json
│ ├── setting.json
│ └── sticker.json
├── group
│ ├── antilink.json
│ ├── antinsfw.json
│ ├── autosticker.json
│ ├── badwords.json
│ ├── leveling.json
│ ├── nsfw.json
│ └── welcome.json
└── user
│ ├── afk.json
│ ├── daily.json
│ ├── level.json
│ ├── limit.json
│ └── reminder.json
├── function
├── afk.js
├── daily.js
├── index.js
├── level.js
├── limit.js
├── loader.js
├── premium.js
├── quizizz.js
├── register.js
└── reminder.js
├── index.js
├── lib
├── downloader.js
├── index.js
└── weeaboo.js
├── message
├── index.js
└── text
│ └── lang
│ ├── eng.js
│ ├── ind.js
│ └── index.js
├── package-lock.json
├── package.json
└── tools
├── fetcher.js
└── index.js
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'env': {
3 | 'es2021': true,
4 | 'node': true
5 | },
6 | 'extends': 'eslint:recommended',
7 | 'parserOptions': {
8 | 'ecmaVersion': 12
9 | },
10 | 'rules': {
11 | 'no-empty': 'warn',
12 | 'no-extra-semi': 'warn',
13 | 'no-unexpected-multiline': 'warn',
14 | 'default-case': 'error',
15 | 'default-case-last': 'error',
16 | 'no-alert': 'warn',
17 | 'no-empty-function': 'warn',
18 | 'no-invalid-this': 'warn',
19 | 'no-useless-catch': 'warn',
20 | 'require-await': 'error',
21 | 'quotes': ['warn', 'single']
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at slavyan@secret.fyi. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | ko_fi: slavyandesu
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/ask.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question
3 | about: Ask anything
4 | title: ''
5 | labels: question
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Question**
11 | What would you like to ask?
12 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/greetings.yml:
--------------------------------------------------------------------------------
1 | name: Greetings
2 |
3 | on: [pull_request, issues]
4 |
5 | jobs:
6 | greeting:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/first-interaction@v1
10 | with:
11 | repo-token: ${{ secrets.GITHUB_TOKEN }}
12 | issue-message: 'Hello! Thanks for submiting the issue, we will respond to you ASAP.'
13 | pr-message: 'Hello! Thank you for contributing to this repo, we will review your commits ASAP.'
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.data.json
3 | logs
4 | .node-persist
5 | _IGNORE_*
6 | temp
7 | **.data.json
8 | **.node-persist**
9 | **_IGNORE_**
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 SlavyanDesu
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # **BocchiBot**
5 |
6 | > BocchiBot is a multipurpose WhatsApp bot using wa-automate-nodejs library!
7 | >
8 | >
9 |
10 |
Made with ❤️ by
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
Requirements •
26 |
Installation •
27 |
Features •
28 |
Thanks to •
29 |
License
30 |
31 |
32 | # Requirements
33 | * [Node.js](https://nodejs.org/en/)
34 | * [Git](https://git-scm.com/downloads)
35 | * [FFmpeg](https://www.gyan.dev/ffmpeg/builds/)
36 | * [Tesseract](https://github.com/tesseract-ocr/tesseract)
37 |
38 | # Installation
39 | ## 📝 Cloning the repo
40 | ```cmd
41 | > git clone https://github.com/SlavyanDesu/BocchiBot.git
42 | > cd BocchiBot
43 | ```
44 |
45 | ## ✍️ Editing the file
46 | Edit the required value in `config.json`.
47 | ```json
48 | {
49 | "ownerBot": "62812xxxxxxxx@c.us",
50 | "prefix": ".",
51 | "nao": "SAUCENAO-API-KEY",
52 | "openAiKey": "OPENAI-API-KEY",
53 | "authorStick": "@SlavyanDesu",
54 | "packStick": "BocchiBot"
55 | }
56 | ```
57 |
58 | `ownerBot`: your WhatsApp number.
59 | `prefix`: bot's prefix.
60 | `nao`: SauceNAO API key. You can get it [here](https://saucenao.com/user.php) by creating an account.
61 | `openAiKey`: OpenAI API key. You can get it [here](https://platform.openai.com/account/api-keys) by creating an account.
62 | `authorStick`: name of the author sticker pack.
63 | `packStick`: name of the sticker pack.
64 |
65 | ## 🗣️ Changing Language
66 | Replace all of `eng` to `ind` for Bahasa Indonesia.
67 |
68 | ## 🛠️ Installing the FFmpeg
69 | * Download one of the available versions of FFmpeg by clicking [this link](https://www.gyan.dev/ffmpeg/builds/).
70 | * Extract the file to `C:\` path.
71 | * Rename the extracted folder to `ffmpeg`.
72 | * Run Command Prompt as Administrator.
73 | * Run this command:
74 | ```cmd
75 | > setx /m PATH "C:\ffmpeg\bin;%PATH%"
76 | ```
77 | It will give us a callback like `SUCCESS: specified value was saved`.
78 | * Now that you've FFmpeg installed, verify that it's working by running this command to see version number:
79 | ```cmd
80 | > ffmpeg -version
81 | ```
82 |
83 | ## 🛠️ Installing the Tesserract
84 | * Download the Tesseract program [here](https://s.id/vftesseract).
85 | * Run the Tesseract program with run As Administrator.
86 | * Make sure the Tesseract installation is in the `C:\` folder
87 | * Run Command Prompt as Administrator.
88 | * Run this command:
89 | ```cmd
90 | > setx /m PATH "C:\Tesseract-OCR;%PATH%"
91 | ```
92 | It will give us a callback like `SUCCESS: specified value was saved`.
93 | * Now that you've Tesseract installed, verify that it's working by running this command to see version number:
94 | ```cmd
95 | > tesseract -version
96 | ```
97 |
98 | ## 🔍 Installing the dependencies
99 | ```cmd
100 | > npm install
101 | ```
102 |
103 | ## 🆗 Running the bot
104 | Regular node:
105 | ```cmd
106 | > npm start
107 | ```
108 |
109 | PM2:
110 | ```cmd
111 | > pm2 start index.js -i max
112 | > pm2 monit
113 | ```
114 |
115 | After that scan the QR code using your WhatsApp in your phone.
116 |
117 | # Features
118 | Type `.help` to your bot number to see the list of commands.
119 |
120 | # Thanks to
121 | * [`open-wa/wa-automate-nodejs`](https://github.com/open-wa/wa-automate-nodejs)
122 | * [`YogaSakti/imageToSticker`](https://github.com/YogaSakti/imageToSticker)
123 | * [`uukina`](https://github.com/uukina)
124 | * [`VideFrelan`](https://github.com/VideFrelan)
125 | * [`Pahri123`](https://github.com/Pahri123)
126 | * [`LeviathanH`](https://github.com/LeviathanH)
127 | * [`ferlitopym`](https://github.com/ferlitopym)
128 | * [`AlvioAdjiJanuar`](https://github.com/Piyoxz)
129 | * [`VirusLauncher`](https://github.com/VirusLauncher)
130 | * [`Sansekai`](https://github.com/Sansekai)
131 | * [`Baguettou`](https://github.com/Baguettou)
132 | * [`HAFizh-15`](https://github.com/HAFizh-15)
133 | * [`TheSploit`](https://github.com/TheSploit)
134 | * [`rashidsiregar28`](https://github.com/rashidsiregar28)
135 | * [`irham01`](https://github.com/irham01)
136 | * [`hardiantojek93`](https://github.com/hardiantojek93)
137 | * [`gamingrkp`](https://github.com/gamingrkp)
138 |
139 | # License
140 | **BocchiBot** © [SlavyanDesu](https://github.com/SlavyanDesu), released under the MIT License.
141 | Authored and maintained by SlavyanDesu.
142 |
143 |
146 |
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "ownerBot": "62xxxxxxx@c.us",
3 | "prefix": ".",
4 | "nao": "api-key",
5 | "openAiKey": "api-key",
6 | "authorStick": "@SlavyanDesu",
7 | "packStick": "BocchiBot"
8 | }
9 |
--------------------------------------------------------------------------------
/database/bot/banned.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/bot/mute.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/bot/premium.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/bot/registered.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/bot/setting.json:
--------------------------------------------------------------------------------
1 | {
2 | "memberLimit": "1",
3 | "groupLimit": "10"
4 | }
--------------------------------------------------------------------------------
/database/bot/sticker.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/group/antilink.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/group/antinsfw.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/group/autosticker.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/group/badwords.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/group/leveling.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/group/nsfw.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/group/welcome.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/user/afk.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/user/daily.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/user/level.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/user/limit.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/database/user/reminder.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/function/afk.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra')
2 |
3 | /**
4 | * Add AFK user.
5 | * @param {string} userId
6 | * @param {string} time
7 | * @param {string} reason
8 | * @param {object} _dir
9 | */
10 | const addAfkUser = (userId, time, reason, _dir) => {
11 | const obj = { id: userId, time: time, reason: reason }
12 | _dir.push(obj)
13 | fs.writeFileSync('./database/user/afk.json', JSON.stringify(_dir))
14 | }
15 |
16 | /**
17 | * Check if user is on AFK state.
18 | * @param {string} userId
19 | * @param {object} _dir
20 | * @returns {boolean}
21 | */
22 | const checkAfkUser = (userId, _dir) => {
23 | let status = false
24 | Object.keys(_dir).forEach((i) => {
25 | if (_dir[i].id === userId) {
26 | status = true
27 | }
28 | })
29 | return status
30 | }
31 |
32 | /**
33 | * Get user AFK reason.
34 | * @param {string} userId
35 | * @param {object} _dir
36 | * @returns {string}
37 | */
38 | const getAfkReason = (userId, _dir) => {
39 | let position = null
40 | Object.keys(_dir).forEach((i) => {
41 | if (_dir[i].id === userId) {
42 | position = i
43 | }
44 | })
45 | if (position !== null) {
46 | return _dir[position].reason
47 | }
48 | }
49 |
50 | /**
51 | * Get user AFK time.
52 | * @param {string} userId
53 | * @param {object} _dir
54 | * @returns {string}
55 | */
56 | const getAfkTime = (userId, _dir) => {
57 | let position = null
58 | Object.keys(_dir).forEach((i) => {
59 | if (_dir[i].id === userId) {
60 | position = i
61 | }
62 | })
63 | if (position !== null) {
64 | return _dir[position].time
65 | }
66 | }
67 |
68 | /**
69 | * Get user AFK ID.
70 | * @param {string} userId
71 | * @param {object} _dir
72 | * @returns {string}
73 | */
74 | const getAfkId = (userId, _dir) => {
75 | let position = null
76 | Object.keys(_dir).forEach((i) => {
77 | if (_dir[i].id === userId) {
78 | position = i
79 | }
80 | })
81 | if (position !== null) {
82 | return _dir[position].id
83 | }
84 | }
85 |
86 | /**
87 | * Get user AFK index position.
88 | * @param {string} userId
89 | * @param {object} _dir
90 | * @returns {number}
91 | */
92 | const getAfkPosition = (userId, _dir) => {
93 | let position = null
94 | Object.keys(_dir).forEach((i) => {
95 | if (_dir[i].id === userId) {
96 | position = i
97 | }
98 | })
99 | return position
100 | }
101 |
102 | module.exports = {
103 | addAfkUser,
104 | checkAfkUser,
105 | getAfkReason,
106 | getAfkTime,
107 | getAfkId,
108 | getAfkPosition
109 | }
--------------------------------------------------------------------------------
/function/daily.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra')
2 |
3 | /**
4 | * Add user daily limit.
5 | * @param {string} userId
6 | * @param {string} dir
7 | * @param {object} _dir
8 | */
9 | const addLimit = (userId, _dir) => {
10 | const obj = { id: userId, time: Date.now() }
11 | _dir.push(obj)
12 | fs.writeFileSync('./database/user/daily.json', JSON.stringify(_dir))
13 | }
14 |
15 | /**
16 | * Get user time left.
17 | * @param {string} userId
18 | * @param {object} _dir
19 | * @returns {number}
20 | */
21 | const getLimit = (userId, _dir) => {
22 | let position = null
23 | Object.keys(_dir).forEach((i) => {
24 | if (_dir[i].id === userId) {
25 | position = i
26 | }
27 | })
28 | if (position !== null) {
29 | return _dir[position].time
30 | }
31 | }
32 |
33 | module.exports = {
34 | addLimit,
35 | getLimit
36 | }
--------------------------------------------------------------------------------
/function/index.js:
--------------------------------------------------------------------------------
1 | exports.level = require('./level')
2 | exports.daily = require('./daily')
3 | exports.limit = require('./limit')
4 | exports.register = require('./register')
5 | exports.afk = require('./afk')
6 | exports.reminder = require('./reminder')
7 | exports.premium = require('./premium')
8 | exports.loader = require('./loader')
9 | exports.quizizz = require('./quizizz')
--------------------------------------------------------------------------------
/function/level.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra')
2 |
3 | /**
4 | * Get user ID from db.
5 | * @param {string} userId
6 | * @param {object} _dir
7 | * @returns {string}
8 | */
9 | const getLevelingId = (userId, _dir) => {
10 | let pos = null
11 | let found = false
12 | Object.keys(_dir).forEach((i) => {
13 | if (_dir[i].id === userId) {
14 | pos = i
15 | found = true
16 | }
17 | })
18 | if (found === false && pos === null) {
19 | const obj = { id: userId, xp: 0, level: 1 }
20 | _dir.push(obj)
21 | fs.writeFileSync('./database/user/level.json', JSON.stringify(_dir))
22 | return userId
23 | } else {
24 | return _dir[pos].id
25 | }
26 | }
27 |
28 | /**
29 | * Get user level from db.
30 | * @param {string} userId
31 | * @param {object} _dir
32 | * @returns {number}
33 | */
34 | const getLevelingLevel = (userId, _dir) => {
35 | let pos = null
36 | let found = false
37 | Object.keys(_dir).forEach((i) => {
38 | if (_dir[i].id === userId) {
39 | pos = i
40 | found = true
41 | }
42 | })
43 | if (found === false && pos === null) {
44 | const obj = { id: userId, xp: 0, level: 1 }
45 | _dir.push(obj)
46 | fs.writeFileSync('./database/user/level.json', JSON.stringify(_dir))
47 | return 1
48 | } else {
49 | return _dir[pos].level
50 | }
51 | }
52 |
53 | /**
54 | * Get user XP from db.
55 | * @param {string} userId
56 | * @param {object} _dir
57 | * @returns {number}
58 | */
59 | const getLevelingXp = (userId, _dir) => {
60 | let pos = null
61 | let found = false
62 | Object.keys(_dir).forEach((i) => {
63 | if (_dir[i].id === userId) {
64 | pos = i
65 | found = true
66 | }
67 | })
68 | if (found === false && pos === null) {
69 | const obj = { id: userId, xp: 0, level: 1 }
70 | _dir.push(obj)
71 | fs.writeFileSync('./database/user/level.json', JSON.stringify(_dir))
72 | return 0
73 | } else {
74 | return _dir[pos].xp
75 | }
76 | }
77 |
78 | /**
79 | * Add user level to db.
80 | * @param {string} userId
81 | * @param {number} amount
82 | * @param {object} _dir
83 | */
84 | const addLevelingLevel = (userId, amount, _dir) => {
85 | let position = null
86 | Object.keys(_dir).forEach((i) => {
87 | if (_dir[i].id === userId) {
88 | position = i
89 | }
90 | })
91 | if (position !== null) {
92 | _dir[position].level += amount
93 | fs.writeFileSync('./database/user/level.json', JSON.stringify(_dir))
94 | }
95 | }
96 |
97 | /**
98 | * Add user XP to db.
99 | * @param {string} userId
100 | * @param {number} amount
101 | * @param {object} _dir
102 | */
103 | const addLevelingXp = (userId, amount, _dir) => {
104 | let position = null
105 | Object.keys(_dir).forEach((i) => {
106 | if (_dir[i].id === userId) {
107 | position = i
108 | }
109 | })
110 | if (position !== null) {
111 | _dir[position].xp += amount
112 | fs.writeFileSync('./database/user/level.json', JSON.stringify(_dir))
113 | }
114 | }
115 |
116 | /**
117 | * Get user rank.
118 | * @param {string} userId
119 | * @param {object} _dir
120 | * @returns {number}
121 | */
122 | const getUserRank = (userId, _dir) => {
123 | let position = null
124 | let found = false
125 | _dir.sort((a, b) => (a.xp < b.xp) ? 1 : -1)
126 | Object.keys(_dir).forEach((i) => {
127 | if (_dir[i].id === userId) {
128 | position = i
129 | found = true
130 | }
131 | })
132 | if (found === false && position === null) {
133 | const obj = { id: userId, xp: 0, level: 1 }
134 | _dir.push(obj)
135 | fs.writeFileSync('./database/user/level.json', JSON.stringify(_dir))
136 | return 99
137 | } else {
138 | return position + 1
139 | }
140 | }
141 |
142 | // Cooldown XP gains to prevent spam
143 | const xpGain = new Set()
144 |
145 | /**
146 | * Check is user exist in set.
147 | * @param {string} userId
148 | * @returns {boolean}
149 | */
150 | const isGained = (userId) => {
151 | return !!xpGain.has(userId)
152 | }
153 |
154 | /**
155 | * Add user in set and delete it when it's 1 minute.
156 | * @param {string} userId
157 | */
158 | const addCooldown = (userId) => {
159 | xpGain.add(userId)
160 | setTimeout(() => {
161 | return xpGain.delete(userId)
162 | }, 60000) // Each minute
163 | }
164 |
165 | module.exports = {
166 | getLevelingId,
167 | getLevelingLevel,
168 | getLevelingXp,
169 | addLevelingLevel,
170 | addLevelingXp,
171 | getUserRank,
172 | isGained,
173 | addCooldown
174 | }
--------------------------------------------------------------------------------
/function/limit.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra')
2 |
3 | /**
4 | * Check limit.
5 | * @param {string} userId
6 | * @param {object} _dir
7 | * @param {number} limitCount
8 | * @param {boolean} isPremium
9 | * @param {boolean} isOwner
10 | * @returns {boolean}
11 | */
12 | const isLimit = (userId, _dir, limitCount, isPremium, isOwner) => {
13 | if (isPremium || isOwner) return false
14 | let found = false
15 | for (let i of _dir) {
16 | if (i.id === userId) {
17 | if (i.limit <= 0) {
18 | found = true
19 | return true
20 | } else {
21 | found = true
22 | return false
23 | }
24 | }
25 | }
26 | if (found === false) {
27 | const obj = { id: userId, limit: limitCount }
28 | _dir.push(obj)
29 | fs.writeFileSync('./database/user/limit.json', JSON.stringify(_dir))
30 | return false
31 | }
32 | }
33 |
34 | /**
35 | * Add limit to user.
36 | * @param {string} userId
37 | * @param {object} _dir
38 | * @param {boolean} isPremium
39 | * @param {boolean} isOwner
40 | */
41 | const addLimit = (userId, _dir, isPremium, isOwner) => {
42 | if (isPremium || isOwner) return false
43 | let pos = null
44 | Object.keys(_dir).forEach((i) => {
45 | if (_dir[i].id === userId) {
46 | pos = i
47 | }
48 | })
49 | if (pos !== null) {
50 | _dir[pos].limit -= 1
51 | fs.writeFileSync('./database/user/limit.json', JSON.stringify(_dir))
52 | }
53 | }
54 |
55 | /**
56 | * Get user's limit.
57 | * @param {string} userId
58 | * @param {object} _dir
59 | * @param {number} limitCount
60 | * @returns {number}
61 | */
62 | const getLimit = (userId, _dir, limitCount) => {
63 | let pos = null
64 | let found = false
65 | Object.keys(_dir).forEach((i) => {
66 | if (_dir[i].id === userId) {
67 | pos = i
68 | found = true
69 | }
70 | })
71 | if (found === false && pos === null) {
72 | const obj = { id: userId, limit: limitCount }
73 | _dir.push(obj)
74 | fs.writeFileSync('./database/user/limit.json', JSON.stringify(_dir))
75 | return limitCount
76 | } else {
77 | return _dir[pos].limit
78 | }
79 | }
80 |
81 | module.exports = {
82 | isLimit,
83 | addLimit,
84 | getLimit
85 | }
--------------------------------------------------------------------------------
/function/loader.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-empty-function */
2 | const fs = require('fs-extra')
3 | const { color } = require('../tools')
4 |
5 | /**
6 | * Returns an array of files.
7 | * @param {*} dirPath
8 | * @param {string[]} [arrayOfFiles]
9 | * @returns {string[]}
10 | */
11 | const getAllDirFiles = (dirPath, arrayOfFiles) => {
12 | const files = fs.readdirSync(dirPath)
13 | arrayOfFiles = arrayOfFiles || []
14 | files.forEach((f) => {
15 | if (fs.statSync(dirPath + '/' + f).isDirectory()) {
16 | arrayOfFiles = getAllDirFiles(dirPath + '/' + f, arrayOfFiles)
17 | } else {
18 | arrayOfFiles.push(f)
19 | }
20 | })
21 | return arrayOfFiles
22 | }
23 |
24 | /**
25 | * Uncache a changes.
26 | * @param {*} module
27 | */
28 | const uncache = (module = '.') => {
29 | return new Promise((resolve, reject) => {
30 | try {
31 | delete require.cache[require.resolve(module)]
32 | resolve()
33 | } catch (err) {
34 | reject(err)
35 | }
36 | })
37 | }
38 |
39 | /**
40 | * Delete file cache.
41 | * @param {*} module
42 | * @param {*} call
43 | */
44 | const nocache = (module, call = () => {}) => {
45 | console.log(color('[WATCH]', 'orange'), color(`=> '${module}'`, 'yellow'), 'file is now being watched by me!')
46 | fs.watchFile(require.resolve(module), async () => {
47 | await uncache(require.resolve(module))
48 | call(module)
49 | })
50 | }
51 |
52 | module.exports = {
53 | getAllDirFiles,
54 | uncache,
55 | nocache
56 | }
--------------------------------------------------------------------------------
/function/premium.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra')
2 | const toMs = require('ms')
3 |
4 | /**
5 | * Add premium user.
6 | * @param {string} userId
7 | * @param {string} expired
8 | * @param {object} _dir
9 | */
10 | const addPremiumUser = (userId, expired, _dir) => {
11 | const obj = { id: userId, expired: Date.now() + toMs(expired) }
12 | _dir.push(obj)
13 | fs.writeFileSync('./database/bot/premium.json', JSON.stringify(_dir))
14 | }
15 |
16 | /**
17 | * Get premium user index position.
18 | * @param {string} userId
19 | * @param {object} _dir
20 | * @returns {Number}
21 | */
22 | const getPremiumPosition = (userId, _dir) => {
23 | let position = null
24 | Object.keys(_dir).forEach((i) => {
25 | if (_dir[i].id === userId) {
26 | position = i
27 | }
28 | })
29 | if (position !== null) {
30 | return position
31 | }
32 | }
33 |
34 | /**
35 | * Get premium user expired.
36 | * @param {string} userId
37 | * @param {object} _dir
38 | * @returns {Number}
39 | */
40 | const getPremiumExpired = (userId, _dir) => {
41 | let position = null
42 | Object.keys(_dir).forEach((i) => {
43 | if (_dir[i].id === userId) {
44 | position = i
45 | }
46 | })
47 | if (position !== null) {
48 | return _dir[position].expired
49 | }
50 | }
51 |
52 | /**
53 | * Check if is user premium.
54 | * @param {string} userId
55 | * @param {object} _dir
56 | * @returns {boolean}
57 | */
58 | const checkPremiumUser = (userId, _dir) => {
59 | let status = false
60 | Object.keys(_dir).forEach((i) => {
61 | if (_dir[i].id === userId) {
62 | status = true
63 | }
64 | })
65 | return status
66 | }
67 |
68 | /**
69 | * Constantly checking premium.
70 | * @param {object} _dir
71 | */
72 | const expiredCheck = (_dir) => {
73 | setInterval(() => {
74 | let position = null
75 | Object.keys(_dir).forEach((i) => {
76 | if (Date.now() >= _dir[i].expired) {
77 | position = i
78 | }
79 | })
80 | if (position !== null) {
81 | console.log(`Premium user expired: ${_dir[position].id}`)
82 | _dir.splice(position, 1)
83 | fs.writeFileSync('./database/bot/premium.json', JSON.stringify(_dir))
84 | }
85 | }, 1000)
86 | }
87 |
88 | /**
89 | * Get all premium user ID.
90 | * @param {object} _dir
91 | * @returns {string[]}
92 | */
93 | const getAllPremiumUser = (_dir) => {
94 | const array = []
95 | Object.keys(_dir).forEach((i) => {
96 | array.push(_dir[i].id)
97 | })
98 | return array
99 | }
100 |
101 | module.exports = {
102 | addPremiumUser,
103 | getPremiumExpired,
104 | getPremiumPosition,
105 | expiredCheck,
106 | checkPremiumUser,
107 | getAllPremiumUser
108 | }
109 |
--------------------------------------------------------------------------------
/function/quizizz.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-async-promise-executor */
2 | const fetch = require('node-fetch')
3 |
4 | /**
5 | * @typedef QuizizzHack
6 | * @property {string} answers
7 | */
8 |
9 | /**
10 | * Quizizz Hack Tools.
11 | * @param {string} pin
12 | * @returns {Promise} answers
13 | */
14 | const quizizz = (pin) => new Promise(async (resolve, reject) => {
15 | if (!pin) return reject('Require Pin Query.')
16 | const Data = await fetch('https://piyo.my.id/hack', {
17 | method: 'POST',
18 | headers: {
19 | 'Accept': 'application/json',
20 | 'Content-Type': 'application/json'
21 | },
22 | body: JSON.stringify({ pin: pin })
23 | })
24 | const Response = await Data.json()
25 | if (Response.status === 400) return reject(Response.message)
26 | resolve(Response)
27 | })
28 |
29 | module.exports = {
30 | quizizz
31 | }
--------------------------------------------------------------------------------
/function/register.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra')
2 |
3 | /**
4 | * Add user to database.
5 | * @param {string} userId
6 | * @param {string} name
7 | * @param {string} time
8 | * @param {string} serial
9 | * @param {object} _dir
10 | */
11 | const addRegisteredUser = (userId, name, time, serial, _dir) => {
12 | const obj = { id: userId, name: name, time: time, serial: serial }
13 | _dir.push(obj)
14 | fs.writeFileSync('./database/bot/registered.json', JSON.stringify(_dir))
15 | }
16 |
17 | /**
18 | * Check is user registered.
19 | * @param {string} userId
20 | * @param {object} _dir
21 | * @returns {boolean}
22 | */
23 | const checkRegisteredUser = (userId, _dir) => {
24 | let status = false
25 | Object.keys(_dir).forEach((i) => {
26 | if (_dir[i].id === userId) {
27 | status = true
28 | }
29 | })
30 | return status
31 | }
32 |
33 | /**
34 | * Check is user registered from given serial.
35 | * @param {string} serial
36 | * @param {object} _dir
37 | * @returns {boolean}
38 | */
39 | const checkRegisteredUserFromSerial = (serial, _dir) => {
40 | let status = false
41 | Object.keys(_dir).forEach((i) => {
42 | if (_dir[i].serial === serial) {
43 | status = true
44 | }
45 | })
46 | return status
47 | }
48 |
49 | /**
50 | * Get registered user ID.
51 | * @param {string} userId
52 | * @param {object} _dir
53 | * @returns {string}
54 | */
55 | const getRegisteredUserId = (userId, _dir) => {
56 | let position = null
57 | Object.keys(_dir).forEach((i) => {
58 | if (_dir[i].id === userId) {
59 | position = i
60 | }
61 | })
62 | if (position !== null) {
63 | return _dir[position].id
64 | }
65 | }
66 |
67 | /**
68 | * Check user name from serial.
69 | * @param {string} serial
70 | * @param {object} _dir
71 | * @returns {string}
72 | */
73 | const getRegisteredNameFromSerial = (serial, _dir) => {
74 | let position = null
75 | Object.keys(_dir).forEach((i) => {
76 | if (_dir[i].serial === serial) {
77 | position = i
78 | }
79 | })
80 | if (position !== null) {
81 | return _dir[position].name
82 | }
83 | }
84 |
85 | /**
86 | * Check user time registration from serial.
87 | * @param {string} serial
88 | * @param {object} _dir
89 | * @returns {string}
90 | */
91 | const getRegisteredTimeFromSerial = (serial, _dir) => {
92 | let position = null
93 | Object.keys(_dir).forEach((i) => {
94 | if (_dir[i].serial === serial) {
95 | position = i
96 | }
97 | })
98 | if (position !== null) {
99 | return _dir[position].time
100 | }
101 | }
102 |
103 | /**
104 | * Check user ID from serial.
105 | * @param {string} serial
106 | * @param {object} _dir
107 | * @returns {string}
108 | */
109 | const getRegisteredIdFromSerial = (serial, _dir) => {
110 | let position = null
111 | Object.keys(_dir).forEach((i) => {
112 | if (_dir[i].serial === serial) {
113 | position = i
114 | }
115 | })
116 | if (position !== null) {
117 | return _dir[position].id
118 | }
119 | }
120 |
121 | /**
122 | * Get random user ID.
123 | * @param {object} _dir
124 | * @returns {string}
125 | */
126 | const getRegisteredRandomId = (_dir) => {
127 | return _dir[Math.floor(Math.random() * _dir.length)].id
128 | }
129 |
130 | /**
131 | * Get position of registered user.
132 | * @param {string} userId
133 | * @param {object} _dir
134 | * @returns {number}
135 | */
136 | const getRegisteredPosition = (userId, _dir) => {
137 | let position = null
138 | Object.keys(_dir).forEach((i) => {
139 | if (_dir[i].id === userId) {
140 | position = i
141 | }
142 | })
143 | return position
144 | }
145 |
146 | module.exports = {
147 | addRegisteredUser,
148 | checkRegisteredUser,
149 | checkRegisteredUserFromSerial,
150 | getRegisteredNameFromSerial,
151 | getRegisteredTimeFromSerial,
152 | getRegisteredIdFromSerial,
153 | getRegisteredRandomId,
154 | getRegisteredUserId,
155 | getRegisteredPosition
156 | }
157 |
--------------------------------------------------------------------------------
/function/reminder.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra')
2 | const toMs = require('ms')
3 |
4 | /**
5 | * Add reminder to user.
6 | * @param {string} userId
7 | * @param {string} message
8 | * @param {number} time
9 | * @param {object} _dir
10 | */
11 | const addReminder = (userId, message, time, _dir) => {
12 | const obj = { id: userId, msg: message, time: Date.now() + toMs(time) }
13 | _dir.push(obj)
14 | fs.writeFileSync('./database/user/reminder.json', JSON.stringify(_dir))
15 | }
16 |
17 | /**
18 | * Get reminder.
19 | * @param {string} userId
20 | * @param {object} _dir
21 | * @returns {number}
22 | */
23 | const getReminderTime = (userId, _dir) => {
24 | let position = null
25 | Object.keys(_dir).forEach((i) => {
26 | if(_dir[i].id === userId) {
27 | position = i
28 | }
29 | })
30 | if (position !== null) {
31 | return _dir[position].time
32 | }
33 | }
34 |
35 | /**
36 | * Get reminder message.
37 | * @param {string} userId
38 | * @param {object} _dir
39 | * @returns {string}
40 | */
41 | const getReminderMsg = (userId, _dir) => {
42 | let position = null
43 | Object.keys(_dir).forEach((i) => {
44 | if (_dir[i].id === userId) {
45 | position = i
46 | }
47 | })
48 | if (position !== null) {
49 | return _dir[position].msg
50 | }
51 | }
52 |
53 | /**
54 | * Get position of reminder.
55 | * @param {string} userId
56 | * @param {object} _dir
57 | * @returns {number}
58 | */
59 | const getReminderPosition = (userId, _dir) => {
60 | let position = null
61 | Object.keys(_dir).forEach((i) => {
62 | if (_dir[i].id === userId) {
63 | position = i
64 | }
65 | })
66 | return position
67 | }
68 |
69 | module.exports = {
70 | addReminder,
71 | getReminderTime,
72 | getReminderMsg,
73 | getReminderPosition
74 | }
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-vars */
2 | const { create, Client } = require('@open-wa/wa-automate')
3 | const { color, options } = require('./tools')
4 | const { eng, ind } = require('./message/text/lang/')
5 | const { loader } = require('./function')
6 | const { version, bugs } = require('./package.json')
7 | const { ownerBot } = require('./config.json')
8 | const { groupLimit, memberLimit } = require('./database/bot/setting.json')
9 | const msgHandler = require('./message/index.js')
10 | const figlet = require('figlet')
11 | const fs = require('fs-extra')
12 | const cron = require('node-cron')
13 | const exec = require('await-exec')
14 |
15 | const start = (bocchi = new Client()) => {
16 | console.log(color(figlet.textSync('BocchiBot', 'Larry 3D'), 'cyan'))
17 | console.log(color('=> Bot successfully loaded! Database:', 'yellow'), color(loader.getAllDirFiles('./database').length), color('Library:', 'yellow'), color(loader.getAllDirFiles('./lib').length), color('Function:', 'yellow'), color(loader.getAllDirFiles('./function').length))
18 | console.log(color('=> Source code version:', 'yellow'), color(version))
19 | console.log(color('=> Bug? Error? Suggestion? Visit here:', 'yellow'), color(bugs.url))
20 | console.log(color('[BOCCHI]'), color('BocchiBot is now online!', 'yellow'))
21 |
22 | if (!fs.existsSync('./temp')) {
23 | console.log(color('=> Temp folder not found! Creating temp folder...', 'yellow'))
24 | fs.mkdirSync('./temp/audio', { recursive: true })
25 | fs.mkdirSync('./temp/video', { recursive: true })
26 | console.log(color('=> Temp folder successfully created!', 'yellow'))
27 | }
28 |
29 | // Uncomment code below to activate auto-update file changes.
30 | // loader.nocache('../message/index.js', (m) => console.log(color('[WATCH]', 'orange'), color(`=> '${m}'`, 'yellow'), 'file is updated!'))
31 |
32 | bocchi.onStateChanged(async (state) => {
33 | console.log(color('[BOCCHI]'), color(state, 'yellow'))
34 | if (state === 'OPENING') {
35 | await bocchi.refresh()
36 | .catch((err) => {
37 | console.log(color('[ERROR]', 'red'), color(err, 'yellow'))
38 | console.log(color('[BOCCHI]'), color('Initiating force restart...', 'yellow'))
39 | exec('pm2 restart all')
40 | })
41 | }
42 | if (state === 'UNPAIRED' || state === 'CONFLICT' || state === 'UNLAUNCHED') await bocchi.forceRefocus()
43 | })
44 |
45 | bocchi.onAddedToGroup(async (chat) => {
46 | const gc = await bocchi.getAllGroups()
47 | console.log(color('[BOCCHI]'), 'Added to a new group. Name:', color(chat.contact.name, 'yellow'), 'Total members:', color(chat.groupMetadata.participants.length, 'yellow'))
48 | if (chat.groupMetadata.participants.includes(ownerBot)) {
49 | await bocchi.sendText(chat.id, eng.addedGroup(chat))
50 | } else if (gc.length > groupLimit) {
51 | await bocchi.sendText(chat.id, `Max groups reached!\n\nCurrent status: ${gc.length}/${groupLimit}`)
52 | await bocchi.clearChat(chat.id)
53 | await bocchi.leaveGroup(chat.id)
54 | } else if (chat.groupMetadata.participants.length < memberLimit) {
55 | await bocchi.sendText(chat.id, `Need at least ${memberLimit} members in group!`)
56 | await bocchi.clearChat(chat.id)
57 | await bocchi.leaveGroup(chat.id)
58 | } else {
59 | await bocchi.sendText(chat.id, eng.addedGroup(chat))
60 | }
61 | })
62 |
63 | bocchi.onMessage((message) => {
64 | // Comment code below to activate auto-update. Then, uncomment require code below msgHandler.
65 | msgHandler(bocchi, message)
66 | // require('./message/index.js')(bocchi, message)
67 | })
68 |
69 | bocchi.onIncomingCall(async (callData) => {
70 | await bocchi.sendText(callData.peerJid, eng.blocked(ownerBot))
71 | await bocchi.contactBlock(callData.peerJid)
72 | console.log(color('[BLOCK]', 'red'), color(`${callData.peerJid} has been blocked.`, 'yellow'))
73 | })
74 |
75 | // Clear chats every 12 hour
76 | cron.schedule('0 */12 * * *', async () => {
77 | const allChats = await bocchi.getAllChats()
78 | for (let chats of allChats) {
79 | if (chats.isGroup === true) {
80 | console.log(color('[BOCCHI]'), color('Clearing chats...', 'yellow'))
81 | await bocchi.clearChat(chats.id)
82 | } else {
83 | await bocchi.deleteChat(chats.id)
84 | }
85 | }
86 | console.log(color('[BOCCHI]'), color('Success cleared all chats!', 'yellow'))
87 | })
88 |
89 | bocchi.onGlobalParticipantsChanged(async (event) => {
90 | const _welcome = JSON.parse(fs.readFileSync('./database/group/welcome.json'))
91 | const isWelcome = _welcome.includes(event.chat)
92 | const gcChat = await bocchi.getChatById(event.chat)
93 | const pcChat = await bocchi.getContact(event.who)
94 | let { pushname, verifiedName, formattedName } = pcChat
95 | pushname = pushname || verifiedName || formattedName
96 | const { groupMetadata } = gcChat
97 | const botNumbers = await bocchi.getHostNumber() + '@c.us'
98 | try {
99 | if (event.action === 'add' && event.who !== botNumbers && isWelcome) {
100 | await bocchi.sendText(event.chat, `Welcome, ${pushname}! You are the *${groupMetadata.participants.length}* member.`)
101 | } else if (event.action === 'remove' && event.who !== botNumbers && isWelcome) {
102 | await bocchi.sendText(event.chat, `Bye, ${pushname}. We will miss you. :(`)
103 | }
104 | } catch (err) {
105 | console.error(err)
106 | }
107 | })
108 | }
109 |
110 | create(options(start))
111 | .then((bocchi) => start(bocchi))
112 | .catch((err) => console.error(err))
--------------------------------------------------------------------------------
/lib/downloader.js:
--------------------------------------------------------------------------------
1 | const { twitter } = require('video-url-link')
2 | const ytdl = require('ytdl-core')
3 | const fs = require('fs-extra')
4 | const { createSerial } = require('../tools/index.js')
5 |
6 | /**
7 | * @typedef TwitterData
8 | * @property {string} full_text
9 | * @property {object[]} variants
10 | */
11 |
12 | /**
13 | * Twitter video downloader.
14 | * @param {string} url
15 | * @returns {Promise}
16 | */
17 | const tweet = (url) => new Promise((resolve, reject) => {
18 | twitter.getInfo(url, {}, (error, info) => {
19 | if (error) {
20 | reject(error)
21 | } else {
22 | resolve(info)
23 | }
24 | })
25 | })
26 |
27 | /**
28 | * @typedef YoutubeData
29 | * @property {string} title
30 | * @property {string} path
31 | */
32 |
33 | /**
34 | * YouTube video downloader.
35 | * @param {string} url
36 | * @param {number} sender
37 | * @returns {Promise} video path
38 | */
39 | const yt = (url, sender) => new Promise((resolve, reject) => {
40 | if (ytdl.validateURL(url)) {
41 | ytdl.getBasicInfo(url)
42 | .then((metadata) => {
43 | const output = `temp/${sender}_${createSerial(5)}.mp4`
44 | ytdl(url)
45 | .pipe(fs.createWriteStream(output))
46 | .on('finish', () => {
47 | const obj = {
48 | title: metadata.videoDetails.title,
49 | path: output
50 | }
51 | resolve(obj)
52 | })
53 | .on('error', (err) => {
54 | reject(err)
55 | })
56 | })
57 | } else {
58 | reject('Not a valid URL.')
59 | }
60 | })
61 |
62 | module.exports = {
63 | tweet,
64 | yt
65 | }
66 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | exports.weeaboo = require('./weeaboo')
2 | exports.downloader = require('./downloader')
3 |
--------------------------------------------------------------------------------
/lib/weeaboo.js:
--------------------------------------------------------------------------------
1 | const { fetchJson } = require('../tools/fetcher')
2 |
3 | /**
4 | * Get random waifu image.
5 | * @param {boolean} [nsfw=false]
6 | * @returns {Promise}
7 | */
8 | const waifu = (nsfw) => new Promise((resolve, reject) => {
9 | if (nsfw === true) {
10 | console.log('Get NSFW waifu image...')
11 | fetchJson('https://waifu.pics/api/nsfw/waifu')
12 | .then((result) => resolve(result))
13 | .catch((err) => reject(err))
14 | } else {
15 | console.log('Get SFW waifu image...')
16 | fetchJson('https://waifu.pics/api/sfw/waifu')
17 | .then((result) => resolve(result))
18 | .catch((err) => reject(err))
19 | }
20 | })
21 |
22 | /**
23 | * Get anime source from image.
24 | * @param {string} url
25 | * @returns {Promise}
26 | */
27 | const wait = (url) => new Promise((resolve, reject) => {
28 | console.log('Searching for source...')
29 | fetchJson(`https://api.trace.moe/search?anilistInfo&url=${encodeURIComponent(url)}`)
30 | .then((result) => resolve(result))
31 | .catch((err) => reject(err))
32 | })
33 |
34 | module.exports = {
35 | waifu,
36 | wait
37 | }
38 |
--------------------------------------------------------------------------------
/message/text/lang/eng.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable quotes */
2 | const { prefix } = require('../../../config.json')
3 |
4 | exports.unreg = () => {
5 | return `Successfully unregistered!`
6 | }
7 |
8 | exports.wait = () => {
9 | return `Please wait a moment...`
10 | }
11 |
12 | exports.ok = () => {
13 | return `Done!`
14 | }
15 |
16 | exports.videoLimit = () => {
17 | return `Video/GIF size is too large!`
18 | }
19 |
20 | exports.wrongFormat = () => {
21 | return `Incorrect format! Please check usage at *${prefix}menu*`
22 | }
23 |
24 | exports.emptyMess = () => {
25 | return `Please enter the message!`
26 | }
27 |
28 | exports.cmdNotFound = (cmd) => {
29 | return `Command *${prefix}${cmd}* not found!`
30 | }
31 |
32 | exports.blocked = (ownerNumber) => {
33 | return `The bot cannot receive calls. You have been blocked because breaking the rules!\n\nContact the owner: wa.me/${ownerNumber.replace('@c.us', '')}`
34 | }
35 |
36 | exports.ownerOnly = () => {
37 | return `This command can only be used by owner!`
38 | }
39 |
40 | exports.groupOnly = () => {
41 | return `This command can only be used in group!`
42 | }
43 |
44 | exports.adminOnly = () => {
45 | return `This command can only be used by group admins!`
46 | }
47 |
48 | exports.addedGroup = (chat) => {
49 | return `Thanks for inviting me, members of *${chat.contact.name}*!\n\nPlease register in *private chat* by typing:\n*${prefix}register* name`
50 | }
51 |
52 | exports.listBlock = (blockNumber) => {
53 | return `
54 | *── 「 HALL OF SHAME 」 ──*
55 |
56 | Total blocked: *${blockNumber.length}* user(s)\n
57 | `
58 | }
59 |
60 | exports.notPremium = () => {
61 | return `Sorry! This command can only be used by premium users.`
62 | }
63 |
64 | exports.notAdmin = () => {
65 | return `The user is not an admin!`
66 | }
67 |
68 | exports.adminAlready = () => {
69 | return `Cannot promote user who is an admin already!`
70 | }
71 |
72 | exports.botNotPremium = () => {
73 | return `This bot doesn't support premium commands. Please contact the owner of this bot.`
74 | }
75 |
76 | exports.botNotAdmin = () => {
77 | return `Make the bot as admin first!`
78 | }
79 |
80 | exports.notRegistered = () => {
81 | return `You haven't registered in our database!\n\nPlease register in *private chat* by typing:\n*${prefix}register* name`
82 | }
83 |
84 | exports.registered = (name, userId, time, serial) => {
85 | return `
86 | *── 「 REGISTRATION 」 ──*
87 |
88 | Your account has been created with data below:
89 | ➸ *Name*: ${name}
90 | ➸ *ID*: ${userId}
91 | ➸ *Registered on*: ${time}
92 | ➸ *Serial*: ${serial}
93 |
94 | Note:
95 | Don't share your *serial* to anyone!
96 |
97 | Type *${prefix}rules* to see the rules.
98 | `
99 | }
100 |
101 | exports.registeredAlready = () => {
102 | return `You've registered before.`
103 | }
104 |
105 | exports.received = (pushname) => {
106 | return `Hello ${pushname}!\nThanks for the report, we will work on it ASAP.`
107 | }
108 |
109 | exports.daily = (time) => {
110 | return `Sorry, but you've reached your limit using this command.\nPlease wait for *${time.hours}* hour(s) *${time.minutes}* minute(s) *${time.seconds}* second(s) more.`
111 | }
112 |
113 | exports.profile = (username, status, premi, benet, adm, level, requiredXp, xp) => {
114 | return `
115 | *── 「 USER INFO」 ──*
116 |
117 | ➸ *Username*: ${username}
118 | ➸ *Status*: ${status}
119 | ➸ *Premium*: ${premi}
120 | ➸ *Banned*: ${benet}
121 | ➸ *Admin*: ${adm}
122 |
123 | =_=_=_=_=_=_=_=_=_=_=_=_=
124 |
125 | *── 「 PROGRESS 」 ──*
126 |
127 | ➸ *Level*: ${level}
128 | ➸ *XP*: ${xp} / ${requiredXp}
129 | `
130 | }
131 |
132 | exports.detectorOn = (name, formattedTitle) => {
133 | return `
134 | *── 「 ANTI GROUP LINK 」 ──*
135 |
136 | Announcement for all *${(name || formattedTitle)}* members.
137 | This group has a group link detector, if someone sends a group link then he'll be kicked out immediately.
138 |
139 | Thanks for your attention.
140 | - Admin *${(name || formattedTitle)}*
141 | `
142 | }
143 |
144 | exports.linkDetected = () => {
145 | return `
146 | *── 「 ANTI GROUP LINK 」 ──*
147 |
148 | You sent a group chat link!
149 | Sorry, but you have to leave...
150 | `
151 | }
152 |
153 | exports.detectorOff = () => {
154 | return `Anti-group link feature was successfully *disabled*!`
155 | }
156 |
157 | exports.detectorOnAlready = () => {
158 | return `Anti-group link feature has been enabled before.`
159 | }
160 |
161 | exports.antiNsfwOn = (name, formattedTitle) => {
162 | return `
163 | *── 「 ANTI NSFW LINK 」 ──*
164 |
165 | Announcement for all *${(name || formattedTitle)}* members.
166 | This group has a NSFW link detector, if someone sends a NSFW link then he'll be kicked out immediately.
167 |
168 | Thanks for your attention.
169 | - Admin *${(name || formattedTitle)}*
170 | `
171 | }
172 |
173 | exports.antiNsfwOff = () => {
174 | return `Anti-NSFW link feature was successfully *disabled*!`
175 | }
176 |
177 | exports.antiNsfwOnAlready = () => {
178 | return `Anti-NSFW link feature has been enabled before.`
179 | }
180 |
181 | exports.antiBadWordsOn = (name, formattedTitle) => {
182 | return `
183 | *── 「 ANTI BAD WORDS 」 ──*
184 |
185 | Announcement for all *${(name || formattedTitle)}* members.
186 | This group has a bad words detector, if someone sends a bad words/profane words then the related message will be deleted.
187 |
188 | Thanks for your attention.
189 | - Admin *${(name || formattedTitle)}*
190 | `
191 | }
192 |
193 | exports.antiBadWordsOff = () => {
194 | return `Anti-bad words feature was successfully *disabled*!`
195 | }
196 |
197 | exports.antiBadWordsOnAlready = () => {
198 | return `Anti-bad words feature has been enabled before.`
199 | }
200 |
201 | exports.antiBadWordsError = () => {
202 | return `Anti-bad words feature is currently *off*, please enable it first.`
203 | }
204 |
205 | exports.levelingOn = () => {
206 | return `Leveling feature was successfully *enabled*!`
207 | }
208 |
209 | exports.levelingOff = () => {
210 | return `Leveling feature was successfully *disabled*!`
211 | }
212 |
213 | exports.levelingOnAlready = () => {
214 | return `Leveling feature has been enabled before.`
215 | }
216 |
217 | exports.levelingNotOn = () => {
218 | return `Leveling feature hasn't been enabled!`
219 | }
220 |
221 | exports.levelNull = () => {
222 | return `You don't have any level yet!`
223 | }
224 |
225 | exports.welcome = (event) => {
226 | return `Welcome @${event.who.replace('@c.us', '')}!`
227 | }
228 |
229 | exports.welcomeOn = () => {
230 | return `Welcome feature was successfully *enabled*!`
231 | }
232 |
233 | exports.welcomeOff = () => {
234 | return `Welcome feature was successfully *disabled*!`
235 | }
236 |
237 | exports.welcomeOnAlready = () => {
238 | return `Welcome feature has been enabled before.`
239 | }
240 |
241 | exports.minimalDb = () => {
242 | return `Need at least *10* users that have a level in database!`
243 | }
244 |
245 | exports.autoStikOn = () => {
246 | return `Auto-sticker feature was successfully *enabled*!`
247 | }
248 |
249 | exports.autoStikOff = () => {
250 | return `Auto-sticker feature was successfully *disabled*!`
251 | }
252 |
253 | exports.autoStikOnAlready = () => {
254 | return `Auto-sticker feature has been enabled before.`
255 | }
256 |
257 | exports.afkOn = (pushname, reason) => {
258 | return `
259 | *── 「 AFK MODE 」 ──*
260 |
261 | AFK feature has been successfully *enabled*!
262 | ➸ *Username*: ${pushname}
263 | ➸ *Reason*: ${reason}
264 | `
265 | }
266 |
267 | exports.afkOnAlready = () => {
268 | return `AFK feature has been enabled before.`
269 | }
270 |
271 | exports.afkMentioned = (getReason, getTime) => {
272 | return `
273 | *── 「 AFK MODE 」 ──*
274 |
275 | Ssshhh! This person is currently AFK!
276 | ➸ *Reason*: ${getReason}
277 | ➸ *Since*: ${getTime}
278 | `
279 | }
280 |
281 | exports.afkDone = (pushname) => {
282 | return `*${pushname}* is back from AFK!`
283 | }
284 |
285 | exports.gcMute = () => {
286 | return `
287 | *── 「 MUTED 」 ──*
288 |
289 | Only admins who can send message in this group.
290 | `
291 | }
292 |
293 | exports.gcUnmute = () => {
294 | return `
295 | *── 「 UNMUTED 」 ──*
296 |
297 | All members can send message in this group now.
298 | `
299 | }
300 |
301 | exports.notNum = (q) => {
302 | return `"${q}", are not a numbers!`
303 | }
304 |
305 | exports.registeredFound = (name, time, serial, userId) => {
306 | return `
307 | *── 「 REGISTERED 」 ──*
308 |
309 | Account has been found!
310 | ➸ *Name*: ${name}
311 | ➸ *ID*: ${userId}
312 | ➸ *Registered time*: ${time}
313 | ➸ *Serial*: ${serial}
314 | `
315 | }
316 |
317 | exports.registeredNotFound = (serial) => {
318 | return `Account with serial: *${serial}* not found!`
319 | }
320 |
321 | exports.pcOnly = () => {
322 | return `This command can only be used in private chat!`
323 | }
324 |
325 | exports.linkNsfw = () => {
326 | return `
327 | *── 「 ANTI NSFW LINK 」 ──*
328 |
329 | You've sent a group link!
330 | Sorry, but you have to leave...
331 | `
332 | }
333 |
334 | exports.fakeLink = () => {
335 | return `The link you sent is suspicious, for the safety of the group I will kick you out.\nBye~.`
336 | }
337 |
338 | exports.muteChatOn = () => {
339 | return `Successfully *mute* bot for this group!`
340 | }
341 |
342 | exports.muteChatOff = () => {
343 | return `Successfully *unmute* bot for this group!`
344 | }
345 |
346 | exports.muteChatOnAlready = () => {
347 | return `Bot is already muted in this group!`
348 | }
349 |
350 | exports.limit = () => {
351 | return `
352 | *── 「 LIMIT 」 ──*
353 |
354 | You ran out of usage limit! Please do the following:
355 | ❏ *_Wait until 12:00 AM (UTC+7)_*
356 | `
357 | }
358 |
359 | exports.reminderOn = (messRemind, parsedTime, sender) => {
360 | return `
361 | *── 「 REMINDER 」 ──*
362 |
363 | Reminder has been set!
364 | ➸ *Message*: ${messRemind}
365 | ➸ *Duration*: ${parsedTime.hours} hour(s) ${parsedTime.minutes} minute(s) ${parsedTime.seconds} second(s)
366 | ➸ *For*: @${sender.id.replace('@c.us', '')}
367 | `
368 | }
369 |
370 | exports.reminderAlert = (messRemind, sender) => {
371 | return `
372 | *── 「 REMINDER 」 ──*
373 |
374 | ⏰ @${sender.id.replace('@c.us', '')} ⏰
375 | ➸ *Message*: ${messRemind}`
376 | }
377 |
378 | exports.nameChanged = (q) => {
379 | return `Username has been changed to *${q}*`
380 | }
381 |
382 | exports.menu = (jumlahUser, level, xp, role, pushname, requiredXp, premium) => {
383 | return `
384 | *── 「 WELCOME 」 ──*
385 |
386 | ======================
387 | ➸ *Name*: ${pushname}
388 | ➸ *Level*: ${level}
389 | ➸ *XP*: ${xp} / ${requiredXp}
390 | ➸ *Role*: ${role}
391 | ➸ *Premium*: ${premium}
392 | ======================
393 |
394 | Total registered: *${jumlahUser}*
395 |
396 | *[1]* Downloader
397 | *[2]* Bot
398 | *[3]* Misc
399 | *[4]* Sticker
400 | *[5]* Weeaboo
401 | *[6]* Fun
402 | *[7]* Moderation
403 | *[8]* Owner
404 | *[9]* Leveling
405 | *[10]* AI
406 |
407 | Type *${prefix}menu* index_number to open the selected page menu.
408 |
409 | Note:
410 | The bot has a cooldown for *5 seconds* every time you use it.
411 | `
412 | }
413 |
414 | exports.menuDownloader = () => {
415 | return `
416 | *── 「 DOWNLOADER 」 ──*
417 |
418 | 1. *${prefix}twitter*
419 | Download Twitter media.
420 | Aliases: *twt*
421 | Usage: *${prefix}twitter* link
422 |
423 | 2. *${prefix}youtube*
424 | Download YouTube video.
425 | Aliases: *yt*
426 | Usage: *${prefix}youtube* link
427 |
428 | _Index of [1]_
429 | `
430 | }
431 |
432 | exports.menuBot = () => {
433 | return `
434 | *── 「 BOT 」 ──*
435 |
436 | 1. *${prefix}rules*
437 | Must read.
438 | Aliases: *rule*
439 | Usage: *${prefix}rules*
440 |
441 | 2. *${prefix}menu*
442 | Display available commands.
443 | Aliases: -
444 | Usage: *${prefix}menu* index_number
445 |
446 | 3. *${prefix}status*
447 | Display bot status.
448 | Aliases: *stats*
449 | Usage: *${prefix}status*
450 |
451 | 4. *${prefix}listblock*
452 | Check blocked numbers.
453 | Aliases: -
454 | Usage: *${prefix}listblock*
455 |
456 | 5. *${prefix}ping*
457 | Check bot speed.
458 | Aliases: *p*
459 | Usage: *${prefix}ping*
460 |
461 | 6. *${prefix}delete*
462 | Delete messages from bot.
463 | Aliases: *del*
464 | Usage: Reply to deleted messages with a caption *${prefix}delete*
465 |
466 | 7. *${prefix}report*
467 | Report bugs to owner.
468 | Aliases: -
469 | Usage: *${prefix}report* text
470 |
471 | 8. *${prefix}tos*
472 | Terms of service.
473 | Aliases: -
474 | Usage: *${prefix}tos*
475 |
476 | 9. *${prefix}join*
477 | Join a group via link.
478 | Aliases: -
479 | Usage: *${prefix}join* group_link
480 |
481 | 10. *${prefix}ownerbot*
482 | Send owner contact.
483 | Aliases: -
484 | Usage: *${prefix}ownerbot*
485 |
486 | 11. *${prefix}getpic*
487 | Send user's profile pic.
488 | Aliases: -
489 | Usage: *${prefix}getpic* @user/62812xxxxxxxx
490 |
491 | 12. *${prefix}premiumcheck*
492 | Check your remaining premium time limit.
493 | Aliases: *cekpremium*
494 | Usage: *${prefix}premiumcheck*
495 |
496 | 13. *${prefix}premiumlist*
497 | Premium user list.
498 | Aliases: *listpremium*
499 | Usage: *${prefix}premiumlist*
500 |
501 | 14. *${prefix}limit*
502 | Check your remaining limit.
503 | Aliases: -
504 | Usage: *${prefix}limit*
505 |
506 | 15. *${prefix}serial*
507 | Check your bio using serial.
508 | Aliases: -
509 | Usage: *${prefix}serial* serial
510 |
511 | 16. *${prefix}runtime*
512 | Check your host runtime.
513 | Aliases: -
514 | Usage: *${prefix}runtime*
515 |
516 | 17. *${prefix}unregister*
517 | Unregister your account.
518 | Aliases: *unreg*
519 | Usage: *${prefix}unregister*
520 |
521 | _Index of [2]_
522 | `
523 | }
524 |
525 | exports.menuMisc = () => {
526 | return `
527 | *── 「 MISC 」 ──*
528 |
529 | 1. *${prefix}say*
530 | The bot will repeat your message.
531 | Aliases: -
532 | Usage: *${prefix}say* text
533 |
534 | 2. *${prefix}tts*
535 | Create a text to speech audio. You can find language code here https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
536 | Aliases: -
537 | Usage: *${prefix}tts* language_code | text
538 |
539 | 3. *${prefix}afk*
540 | Set your account to AFK mode.
541 | Aliases: -
542 | Usage: *${prefix}afk* reason. Send any message to group to disable.
543 |
544 | 4. *${prefix}math*
545 | A calculator.
546 | * = multiplication
547 | + = addition
548 | - = subtraction
549 | / = division
550 | Aliases: -
551 | Usage: *${prefix}math* 12*12
552 |
553 | 5. *${prefix}reminder*
554 | Reminder.
555 | *s* - seconds
556 | *m* - minutes
557 | *h* - hours
558 | *d* - days
559 | Aliases: -
560 | Usage: *${prefix}reminder* 10s | reminder_message
561 |
562 | 6. *${prefix}imagetourl*
563 | Image uploader.
564 | Aliases: *imgtourl*
565 | Usage: Send images with caption *${prefix}imagetourl* or reply to the image with a caption *${prefix}imagetourl*
566 |
567 | 7. *${prefix}genshininfo*
568 | Genshin Impact characters info.
569 | Aliases: *genshin*
570 | Usage: *${prefix}genshininfo* chara_name
571 |
572 | 8. *${prefix}translate*
573 | Translate a text.
574 | Aliases: *tl*
575 | Usage: *${prefix}translate* text | code_lang
576 |
577 | 9. *${prefix}tomp3*
578 | Convert a video to audio only (MP3).
579 | Aliases: -
580 | Usage: Send a video with caption *${prefix}tomp3* or reply video with a caption *${prefix}tomp3*
581 |
582 | 10. *${prefix}bass*
583 | Bass boost.
584 | Aliases: -
585 | Usage: Reply audio/voice with caption *${prefix}bass* dB_level.
586 |
587 | 11. *${prefix}nightcore*
588 | Create a nightcore effect.
589 | Aliases: -
590 | Usage: Reply audio/voice with caption *${prefix}nightcore*
591 |
592 | 12. *${prefix}google*
593 | Search through Google.
594 | Aliases: *googlesearch*
595 | Usage: *${prefix}google* query
596 |
597 | 13. *${prefix}toptt*
598 | Create PTT audio.
599 | Aliases: *ptt*
600 | Usage: Reply audio/voice with caption *${prefix}toptt*
601 |
602 | _Index of [3]_
603 | `
604 | }
605 |
606 | exports.menuSticker = () => {
607 | return `
608 | *── 「 STICKER 」 ──*
609 |
610 | 1. *${prefix}sticker*
611 | Create stickers from images sent or replied.
612 | Aliases: *stiker*
613 | Usage: Send images with caption *${prefix}sticker* or reply to the images with a caption *${prefix}sticker*
614 |
615 | 2. *${prefix}stickergif*
616 | Create stickers from videos/GIFs.
617 | Aliases: *stikergif* *sgif*
618 | Usage: Send videos/GIFs with caption *${prefix}stickergif* or reply to the videos/GIFs with a caption *${prefix}stickergif*
619 |
620 | 3. *${prefix}stickertoimg*
621 | Convert sticker to image.
622 | Aliases: *stikertoimg* *toimg*
623 | Usage: Reply to the stickers with a caption *${prefix}stickertoimg*
624 |
625 | 4. *${prefix}stickerwm*
626 | Create a sticker with metadata/WM.
627 | Aliases: *stcwm*
628 | Usage: Send images with caption *${prefix}stickerwm* pack_name | author_name or reply to the image with a caption *${prefix}stickerwm* pack_name | author_name
629 |
630 | 5. *${prefix}stickermeme*
631 | Create a sticker meme.
632 | Aliases: *stcmeme*
633 | Usage: Send images with caption *${prefix}sticker* upper_text | bottom_text or reply to the images with a caption *${prefix}sticker* upper_text | bottom_text
634 |
635 | 6. *${prefix}takestick*
636 | Edit sticker metadata.
637 | Aliases: *take*
638 | Usage: Reply to the stickers with a caption *${prefix}takestick* pack_name | author_name
639 |
640 | 7. *${prefix}stickernobg*
641 | Create stickers from images sent or replied with blank background.
642 | Aliases: *take*
643 | Usage: Send images with caption *${prefix}stickernobg* or reply to the images with a caption *${prefix}stickernobg*
644 |
645 | _Index of [4]_
646 | `
647 | }
648 |
649 | exports.menuWeeaboo = () => {
650 | return `
651 | *── 「 WEEABOO 」 ──*
652 |
653 | 1. *${prefix}neko*
654 | Send a neko girl photo.
655 | Aliases: -
656 | Usage: *${prefix}neko*
657 |
658 | 2. *${prefix}wallpaper*
659 | Send anime wallpapers.
660 | Aliases: *wp*
661 | Usage: *${prefix}wallpaper*
662 |
663 | 3. *${prefix}kemono*
664 | Send kemonomimi girl photos.
665 | Aliases: -
666 | Usage: *${prefix}kemono*
667 |
668 | 4. *${prefix}wait*
669 | Search anime source from the screenshots scene.
670 | Aliases: -
671 | Usage: Send screenshots with caption *${prefix}wait* or reply to the screenshots with a caption *${prefix}wait*
672 |
673 | 5. *${prefix}source*
674 | Look for sources from the doujin panel, illustrations, and images related to anime.
675 | Aliases: *sauce*
676 | Usage: Send images with caption *${prefix}source* or reply to the images with a caption *${prefix}source*
677 |
678 | 6. *${prefix}waifu*
679 | Send random waifu photos.
680 | Aliases: -
681 | Usage: *${prefix}waifu*
682 |
683 | _Index of [5]_
684 | `
685 | }
686 |
687 | exports.menuFun = () => {
688 | return `
689 | *── 「 FUN 」 ──*
690 |
691 | 1. *${prefix}triggered*
692 | Apply a triggered effect to image.
693 | Aliases: -
694 | Usage: Send image with caption *${prefix}triggered* or reply to someone message with caption *${prefix}triggered* or you can directly use *${prefix}triggered*
695 |
696 | 2. *${prefix}kiss*
697 | Kiss someone ( ͡° ͜ʖ ͡°).
698 | Aliases: -
699 | Usage: Send image with caption *${prefix}kiss* or reply image with caption *${prefix}kiss*
700 |
701 | 3. *${prefix}profile*
702 | Check my profile.
703 | Aliases: *me*
704 | Usage: *${prefix}profile*
705 |
706 | 4. *${prefix}trash*
707 | Trash?
708 | Aliases: -
709 | Usage: *${prefix}trash*
710 |
711 | 5. *${prefix}hitler*
712 | Worse than hitler.
713 | Aliases: -
714 | Usage: *${prefix}hitler*
715 |
716 | _Index of [6]_
717 | `
718 | }
719 |
720 | exports.menuModeration = () => {
721 | return `
722 | *── 「 MODERATION 」 ──*
723 |
724 | 1. *${prefix}add*
725 | Add users to group.
726 | Aliases: -
727 | Usage: *${prefix}add* 628xxxxxxxxxx
728 |
729 | 2. *${prefix}kick*
730 | Remove members from the group.
731 | Aliases: -
732 | Usage: *${prefix}kick* @member1
733 |
734 | 3. *${prefix}promote*
735 | Promote member to become admin.
736 | Aliases: -
737 | Usage: *${prefix}promote* @member1
738 |
739 | 4. *${prefix}demote*
740 | Demote member from admin.
741 | Aliases: -
742 | Usage: *${prefix}demote* @member1
743 |
744 | 5. *${prefix}leave*
745 | Leave bot from group.
746 | Aliases: -
747 | Usage: *${prefix}leave*
748 |
749 | 6. *${prefix}everyone*
750 | Mention all group members.
751 | Aliases: -
752 | Usage: *${prefix}everyone*
753 |
754 | 7. *${prefix}groupicon*
755 | Change group icon.
756 | Aliases: -
757 | Usage: Send images with caption *${prefix}groupicon* or reply to the images with a caption *${prefix}groupicon*
758 |
759 | 8. *${prefix}antilink*
760 | Toogle anti-group link feature.
761 | Aliases: -
762 | Usage: *${prefix}antilink* enable/disable
763 |
764 | 9. *${prefix}welcome*
765 | Toogle welcome feature.
766 | Aliases: -
767 | Usage: *${prefix}welcome* enable/disable
768 |
769 | 10. *${prefix}autosticker*
770 | Toogle auto-sticker feature. Every sended image will made into a sticker.
771 | Aliases: *autostiker autostik*
772 | Usage: *${prefix}autostiker* enable/disable
773 |
774 | 11. *${prefix}antinsfw*
775 | Toogle anti-NSFW link.
776 | Aliases: -
777 | Usage: *${prefix}antinsfw* enable/disable
778 |
779 | 12. *${prefix}mutegc*
780 | Set group to admin only who can send a message.
781 | Aliases: -
782 | Usage: *${prefix}mutegc* enable/disable
783 |
784 | 13. *${prefix}grouplink*
785 | Send a invite link of current group.
786 | Aliases: -
787 | Usage: *${prefix}grouplink*
788 |
789 | 14. *${prefix}revoke*
790 | Revoke invite link of current group.
791 | Aliases: -
792 | Usage: *${prefix}revoke*
793 |
794 | 15. *${prefix}leveling*
795 | Toogle leveling feature.
796 | Aliases: -
797 | Usage: *${prefix}leveling* enable/disable
798 |
799 | 16. *${prefix}badwords*
800 | Setting up anti-bad words feature.
801 | Aliases: *badword*
802 | Usage: *${prefix}badwords* enable/disable or add/remove to add/remove a blacklist words.
803 |
804 | _Index of [7]_
805 | `
806 | }
807 |
808 | exports.menuOwner = () => {
809 | return `
810 | *── 「 OWNER 」 ──*
811 |
812 | 1. *${prefix}bc*
813 | Create a broadcast.
814 | Aliases: -
815 | Usage: *${prefix}bc* text
816 |
817 | 2. *${prefix}clearall*
818 | Deletes all chats on the bot account.
819 | Aliases: -
820 | Usage: *${prefix}clearall*
821 |
822 | 3. *${prefix}getses*
823 | Take a screenshot of the session from the bot account.
824 | Aliases: -
825 | Usage: *${prefix}getses*
826 |
827 | 4. *${prefix}ban*
828 | Add/remove banned users.
829 | Aliases: -
830 | Usage: *${prefix}ban* add/del @user/62812xxxxxxxx
831 |
832 | 5. *${prefix}leaveall*
833 | Leave from all groups.
834 | Aliases: -
835 | Usage: *${prefix}leaveall*
836 |
837 | 6. *${prefix}eval*
838 | Evaluate the JavaScript code.
839 | Aliases: *ev*
840 | Usage: *${prefix}eval*
841 |
842 | 7. *${prefix}shutdown*
843 | Shutdown bot.
844 | Aliases: -
845 | Usage: *${prefix}shutdown*
846 |
847 | 8. *${prefix}premium*
848 | Add/remove premium user.
849 | *s* - seconds
850 | *m* - minutes
851 | *h* - hours
852 | *d* - days
853 | Aliases: -
854 | Usage: *${prefix}premium* add/del @user/62812xxxxxxxx 30d
855 |
856 | 9. *${prefix}setstatus*
857 | Set about me.
858 | Aliases: *setstatus setstat*
859 | Usage: *${prefix}status* text
860 |
861 | 10. *${prefix}serial*
862 | Check user's serial.
863 | Aliases: -
864 | Usage: *${prefix}serial* user_serial
865 |
866 | 11. *${prefix}exif*
867 | Adjust your sticker WM.
868 | Aliases: -
869 | Usage: *${prefix}exif* pack_name | author_name
870 |
871 | 12. *${prefix}mute*
872 | Mute all users.
873 | Aliases: -
874 | Usage: Use *${prefix}mute* to mute and use *${prefix}mute* once again to unmute.
875 |
876 | 13. *${prefix}setname*
877 | Change bot's name. Maximum 25 characters.
878 | Aliases: -
879 | Usage: *${prefix}name* new_username
880 |
881 | 14. *${prefix}block*
882 | Block user.
883 | Aliases: *blok*
884 | Usage: *${prefix}block* @user/62812xxxxxxxx
885 |
886 | 15. *${prefix}unblock*
887 | Unblock user.
888 | Aliases: *unblok*
889 | Usage: *${prefix}unblock* @user/62812xxxxxxxx
890 |
891 | 16. *${prefix}xp*
892 | Add XP to someone.
893 | Aliases: -
894 | Usage: *${prefix}xp* @user amount_xp
895 |
896 | _Index of [8]_
897 | `
898 | }
899 |
900 | exports.menuLeveling = () => {
901 | return `
902 | *── 「 LEVELING 」 ──*
903 |
904 | 1. *${prefix}level*
905 | Check your level.
906 | Aliases: -
907 | Usage: *${prefix}level*
908 |
909 | 2. *${prefix}leaderboard*
910 | Check leaderboard.
911 | Aliaases: -
912 | Usage: *${prefix}leaderboard*
913 |
914 | _Index of [9]_
915 | `
916 | }
917 |
918 | exports.menuAi = () => {
919 | return `
920 | *── 「 AI 」 ──*
921 |
922 | 1. *${prefix}ai*
923 | ChatGPT 3.5 implementation.
924 | Aliases: -
925 | Usage: *${prefix}ai* your_question
926 |
927 | 2. *${prefix}image*
928 | Create image from given prompt.
929 | Aliases: *img*
930 | Usage: *${prefix}image* prompt
931 |
932 | _Index of [10]_
933 | `
934 | }
935 |
936 | exports.rules = () => {
937 | return `
938 | *── 「 RULES 」 ──*
939 |
940 | 1. Do NOT spam bot.
941 | Penalty: *WARN/SOFT BLOCK*
942 |
943 | 2. Do NOT call bot.
944 | Penalty: *SOFT BLOCK*
945 |
946 | 3. Do NOT exploit bots.
947 | Penalty: *PERMANENT BLOCK*
948 |
949 | If you've understand these rules, please type *${prefix}menu* to get started.
950 | `
951 | }
952 |
953 | // Note for owner/hoster, please DO NOT edit this section.
954 | exports.tos = (ownerNumber) => {
955 | return `
956 | *── 「 TERMS OF SERVICE 」 ──*
957 |
958 | This bot is an open-source bot, come with the name of BocchiBot which is available on GitHub for free.
959 | The owner/hoster of this bot is independent from the responsibility and supervision of the developer (Slavyan).
960 | Owner/hoster may plagiarize, add, delete, replace source code with notes *DO NOT SELL* this source code in any form.
961 | If an error occurs, the first person you should contact is the owner/hoster.
962 |
963 | If you want to contributing to this project, visit:
964 | https://github.com/SlavyanDesu/BocchiBot
965 |
966 | Contact person:
967 | wa.me/${ownerNumber.replace('@c.us', '')} (Owner/hoster)
968 |
969 | Regards,
970 | Slavyan
971 | `
972 | }
973 |
--------------------------------------------------------------------------------
/message/text/lang/ind.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable quotes */
2 | const { prefix } = require('../../../config.json')
3 |
4 | exports.wait = () => {
5 | return `Mohon tunggu sebentar...`
6 | }
7 |
8 | exports.ok = () => {
9 | return `Done!`
10 | }
11 |
12 | exports.videoLimit = () => {
13 | return `Ukuran video/GIF terlalu besar!`
14 | }
15 |
16 | exports.wrongFormat = () => {
17 | return `Format salah! Silakan cek cara penggunaan di *${prefix}menu*.`
18 | }
19 |
20 | exports.emptyMess = () => {
21 | return `Harap masukkan pesan yang ingin disampaikan!`
22 | }
23 |
24 | exports.cmdNotFound = (cmd) => {
25 | return `Command *${prefix}${cmd}* tidak ditemukan!`
26 | }
27 |
28 | exports.blocked = (ownerNumber) => {
29 | return `Bot tidak menerima panggilan. Kamu diblokir karena telah melanggar rules!\n\nHubungi owner: wa.me/${ownerNumber.replace('@c.us', '')}`
30 | }
31 |
32 | exports.ownerOnly = () => {
33 | return `Command ini hanya bisa digunakan oleh owner!`
34 | }
35 |
36 | exports.groupOnly = () => {
37 | return `Command ini hanya bisa digunakan di dalam grup!`
38 | }
39 |
40 | exports.adminOnly = () => {
41 | return `Command ini hanya bisa digunakan oleh admin grup!`
42 | }
43 |
44 | exports.addedGroup = (chat) => {
45 | return `Terima kasih telah mengundangku, para member *${chat.contact.name}*!\n\nSilakan register di *private chat* dengan format:\n*${prefix}register* nama`
46 | }
47 |
48 | exports.listBlock = (blockNumber) => {
49 | return `
50 | *── 「 HALL OF SHAME 」 ──*
51 |
52 | Total user diblokir: *${blockNumber.length}*\n
53 | `
54 | }
55 |
56 | exports.notPremium = () => {
57 | return `Maaf! Command ini khusus untuk user premium saja.`
58 | }
59 |
60 | exports.notAdmin = () => {
61 | return `User bukan seorang admin!`
62 | }
63 |
64 | exports.adminAlready = () => {
65 | return `Tidak dapat mem-promote user yang merupakan admin!`
66 | }
67 |
68 | exports.botNotPremium = () => {
69 | return `Bot ini tidak mendukung command premium. Silakan hubungi pemilik bot ini.`
70 | }
71 |
72 | exports.botNotAdmin = () => {
73 | return `Jadikan bot sebagai admin terlebih dahulu!`
74 | }
75 |
76 | exports.notRegistered = () => {
77 | return `Kamu belum terdaftar di database!\n\nSilakan register di *private chat* dengan format:\n*${prefix}register* nama`
78 | }
79 |
80 | exports.registered = (name, userId, time, serial) => {
81 | return `
82 | *── 「 REGISTRATION 」 ──*
83 |
84 | Akun kamu telah terdaftar dengan data:
85 | ➸ *Nama*: ${name}
86 | ➸ *ID*: ${userId}
87 | ➸ *Waktu pendaftaran*: ${time}
88 | ➸ *Serial*: ${serial}
89 |
90 | Catatan:
91 | Jangan pernah menyebarkan data *serial* ke pada siapapun!
92 |
93 | Ketik *${prefix}rules* terlebih dahulu ya~
94 | `
95 | }
96 |
97 | exports.registeredAlready = () => {
98 | return `Kamu sudah mendaftar sebelumnya.`
99 | }
100 |
101 | exports.received = (pushname) => {
102 | return `Halo ${pushname}!\nTerima kasih telah melapor, laporanmu akan kami segera terima.`
103 | }
104 |
105 | exports.daily = (time) => {
106 | return `Maaf, tetapi kamu telah mencapai limit menggunakan command ini.\nSilakan tunggu *${time.hours}* jam *${time.minutes}* menit *${time.seconds}* detik lagi.`
107 | }
108 |
109 | exports.profile = (username, status, premi, benet, adm, level, requiredXp, xp) => {
110 | return `
111 | *── 「 USER INFO」 ──*
112 |
113 | ➸ *Username*: ${username}
114 | ➸ *Status*: ${status}
115 | ➸ *Premium*: ${premi}
116 | ➸ *Banned*: ${benet}
117 | ➸ *Admin*: ${adm}
118 |
119 | =_=_=_=_=_=_=_=_=_=_=_=_=
120 |
121 | *── 「 PROGRESS 」 ──*
122 |
123 | ➸ *Level*: ${level}
124 | ➸ *XP*: ${xp} / ${requiredXp}
125 | `
126 | }
127 |
128 | exports.detectorOn = (name, formattedTitle) => {
129 | return `
130 | *── 「 ANTI GROUP LINK 」 ──*
131 |
132 | Pengumuman untuk member *${(name || formattedTitle)}*.
133 | Grup ini memiliki group link detector, apabila ada member yang mengirim group link, maka dia akan ter-kick secara otomatis.
134 |
135 | Sekian terima kasih.
136 | - Admin *${(name || formattedTitle)}*
137 | `
138 | }
139 |
140 | exports.linkDetected = () => {
141 | return `
142 | *── 「 ANTI GROUP LINK 」 ──*
143 |
144 | Kamu mengirim link group chat!
145 | Maaf tapi kamu harus keluar...
146 | `
147 | }
148 |
149 | exports.detectorOff = () => {
150 | return `Fitur anti-group link berhasil *dinonaktifkan*!`
151 | }
152 |
153 | exports.detectorOnAlready = () => {
154 | return `Fitur anti-group link telah diaktifkan sebelumnya.`
155 | }
156 |
157 | exports.antiNsfwOn = (name, formattedTitle) => {
158 | return `
159 | *── 「 ANTI NSFW LINK 」 ──*
160 |
161 | Pengumuman untuk member *${(name || formattedTitle)}*.
162 | Grup ini memiliki NSFW link detector, apabila ada member yang mengirim NSFW link, maka dia akan ter-kick secara otomatis.
163 |
164 | Sekian terima kasih.
165 | - Admin *${(name || formattedTitle)}*
166 | `
167 | }
168 |
169 | exports.antiNsfwOff = () => {
170 | return `Fitur anti-NSFW link berhasil *dinonaktifkan*!`
171 | }
172 |
173 | exports.antiNsfwOnAlready = () => {
174 | return `Fitur anti-NSFW link telah diaktifkan sebelumnya.`
175 | }
176 |
177 | exports.antiBadWordsOn = (name, formattedTitle) => {
178 | return `
179 | *── 「 ANTI BAD WORDS 」 ──*
180 |
181 | Pengumuman untuk member *${(name || formattedTitle)}*.
182 | Grup ini memiliki bad word detector, apabila ada member yang mengirim bad word/kata kasar, maka pesannya akan segera dihapus.
183 |
184 | Sekian terima kasih.
185 | - Admin *${(name || formattedTitle)}*
186 | `
187 | }
188 |
189 | exports.antiBadWordsOff = () => {
190 | return `Fitur anti-bad word berhasil *dinonaktifkan*!`
191 | }
192 |
193 | exports.antiBadWordsOnAlready = () => {
194 | return `Fitur anti-bad word telah diaktifkan sebelumnya.`
195 | }
196 |
197 | exports.antiBadWordsError = () => {
198 | return `Fitur anti-bad word belum diaktifkan!`
199 | }
200 |
201 | exports.levelingOn = () => {
202 | return `Fitur leveling berhasil *diaktifkan*!`
203 | }
204 |
205 | exports.levelingOff = () => {
206 | return `Fitur leveling berhasil *dinonaktifkan*!`
207 | }
208 |
209 | exports.levelingOnAlready = () => {
210 | return `Fitur leveling telah diaktifkan sebelumnya.`
211 | }
212 |
213 | exports.levelingNotOn = () => {
214 | return `Fitur leveling belum diaktifkan!`
215 | }
216 |
217 | exports.levelNull = () => {
218 | return `Kamu belum memiliki level!`
219 | }
220 |
221 | exports.welcome = (event) => {
222 | return `Selamat datang @${event.who.replace('@c.us', '')}!`
223 | }
224 |
225 | exports.welcomeOn = () => {
226 | return `Fitur welcome berhasil *diaktifkan*!`
227 | }
228 |
229 | exports.welcomeOff = () => {
230 | return `Fitur welcome berhasil *dinonaktifkan*!`
231 | }
232 |
233 | exports.welcomeOnAlready = () => {
234 | return `Fitur welcome telah diaktifkan sebelumnya.`
235 | }
236 |
237 | exports.minimalDb = () => {
238 | return `Perlu setidaknya *10* user yang memiliki level di database!`
239 | }
240 |
241 | exports.autoStikOn = () => {
242 | return `Fitur auto-stiker berhasil *diaktifkan*!`
243 | }
244 |
245 | exports.autoStikOff = () => {
246 | return `Fitur auto-stiker berhasil *dinonaktifkan*!`
247 | }
248 |
249 | exports.autoStikOnAlready = () => {
250 | return `Fitur auto-stiker telah diaktifkan sebelumnya.`
251 | }
252 |
253 | exports.afkOn = (pushname, reason) => {
254 | return `
255 | *── 「 AFK MODE 」 ──*
256 |
257 | Fitur AFK berhasil *diaktifkan*!
258 | ➸ *Username*: ${pushname}
259 | ➸ *Alasan*: ${reason}
260 | `
261 | }
262 |
263 | exports.afkOnAlready = () => {
264 | return `Fitur AFK telah diaktifkan sebelumnya.`
265 | }
266 |
267 | exports.afkMentioned = (getReason, getTime) => {
268 | return `
269 | *── 「 AFK MODE 」 ──*
270 |
271 | Sssttt! Orangnya lagi AFK, jangan diganggu!
272 | ➸ *Alasan*: ${getReason}
273 | ➸ *Sejak*: ${getTime}
274 | `
275 | }
276 |
277 | exports.afkDone = (pushname) => {
278 | return `*${pushname}* telah kembali dari AFK! Selamat datang kembali~`
279 | }
280 |
281 | exports.gcMute = () => {
282 | return `
283 | *── 「 MUTED 」 ──*
284 |
285 | Hanya admin yang dapat mengirim pesan ke grup ini.
286 | `
287 | }
288 |
289 | exports.gcUnmute = () => {
290 | return `
291 | *── 「 UNMUTED 」 ──*
292 |
293 | Sekarang semua anggota dapat mengirim chat di grup ini.
294 | `
295 | }
296 |
297 | exports.notNum = (q) => {
298 | return `"${q}", bukan angka!`
299 | }
300 |
301 | exports.registeredFound = (name, time, serial, userId) => {
302 | return `
303 | *── 「 REGISTERED 」 ──*
304 |
305 | Akun ditemukan!
306 | ➸ *Nama*: ${name}
307 | ➸ *ID*: ${userId}
308 | ➸ *Waktu pendaftaran*: ${time}
309 | ➸ *Serial*: ${serial}
310 | `
311 | }
312 |
313 | exports.registeredNotFound = (serial) => {
314 | return `Akun dengan serial: *${serial}* tidak ditemukan!`
315 | }
316 |
317 | exports.pcOnly = () => {
318 | return `Command ini hanya bisa digunakan di dalam private chat saja!`
319 | }
320 |
321 | exports.linkNsfw = () => {
322 | return `
323 | *── 「 ANTI NSFW LINK 」 ──*
324 |
325 | Kamu telah mengirim link NSFW!
326 | Maaf, tapi aku harus mengeluarkan mu...
327 | `
328 | }
329 |
330 | exports.fakeLink = () => {
331 | return `Ups, link ini terlihat mencurigakan. Demi keamanan grup, aku harus mengeluarkan mu...\n`
332 | }
333 |
334 | exports.muteChatOn = () => {
335 | return `Berhasil *mute* bot pada grup ini!`
336 | }
337 |
338 | exports.muteChatOff = () => {
339 | return `Berhasil *unmute* bot pada grup ini!`
340 | }
341 |
342 | exports.muteChatOnAlready = () => {
343 | return `Mute telah diaktifkan di grup ini sebelumnya!`
344 | }
345 |
346 | exports.limit = () => {
347 | return `
348 | *── 「 LIMIT 」 ──*
349 |
350 | Limit penggunaan kamu telah habis! Silakan lakukan hal berikut:
351 | ❏ *_Tunggu hingga jam 00:00 WIB_*
352 | `
353 | }
354 |
355 | exports.reminderOn = (messRemind, parsedTime, sender) => {
356 | return `
357 | *── 「 REMINDER 」 ──*
358 |
359 | Reminder berhasil diaktifkan!
360 | ➸ *Pesan*: ${messRemind}
361 | ➸ *Durasi*: ${parsedTime.hours} jam ${parsedTime.minutes} menit ${parsedTime.seconds} detik
362 | ➸ *Untuk*: @${sender.id.replace('@c.us', '')}
363 | `
364 | }
365 |
366 | exports.reminderAlert = (messRemind, sender) => {
367 | return `
368 | *── 「 REMINDER 」 ──*
369 |
370 | ⏰ @${sender.id.replace('@c.us', '')} ⏰
371 | ➸ *Pesan*: ${messRemind}`
372 | }
373 |
374 | exports.nameChanged = (q) => {
375 | return `Username berhasil diubah ke *${q}*`
376 | }
377 |
378 | exports.menu = (jumlahUser, level, xp, role, pushname, requiredXp, premium) => {
379 | return `
380 | *── 「 WELCOME 」 ──*
381 |
382 | ======================
383 | ➸ *Nama*: ${pushname}
384 | ➸ *Level*: ${level}
385 | ➸ *XP*: ${xp} / ${requiredXp}
386 | ➸ *Role*: ${role}
387 | ➸ *Premium*: ${premium}
388 | ======================
389 |
390 | Total pendaftar: *${jumlahUser}*
391 |
392 | Berikut adalah menu yang tersedia:
393 |
394 | *[1]* Downloader
395 | *[2]* Bot
396 | *[3]* Misc
397 | *[4]* Sticker
398 | *[5]* Weeaboo
399 | *[6]* Fun
400 | *[7]* Moderation
401 | *[8]* Owner
402 | *[9]* Leveling
403 | *[10]* AI
404 |
405 | Ketik *${prefix}menu* angka_index untuk membuka menu page yang dipilih.
406 |
407 | Catatan:
408 | Bot ini terdapat cooldown command selama *5 detik* setiap kali pemakaian.
409 | `
410 | }
411 |
412 | exports.menuDownloader = () => {
413 | return `
414 | *── 「 DOWNLOADER 」 ──*
415 |
416 | 1. *${prefix}twitter*
417 | Download Twitter media.
418 | Aliases: *twt*
419 | Usage: *${prefix}twitter* link
420 |
421 | 2. *${prefix}youtube*
422 | Download YouTube video.
423 | Aliases: *yt*
424 | Usage: *${prefix}youtube* link
425 |
426 | _Index of [1]_
427 | `
428 | }
429 |
430 | exports.menuBot = () => {
431 | return `
432 | *── 「 BOT 」 ──*
433 |
434 | 1. *${prefix}rules*
435 | Wajib baca.
436 | Aliases: *rule*
437 | Usage: *${prefix}rules*
438 |
439 | 2. *${prefix}menu*
440 | Menampilkan commands yang tersedia.
441 | Aliases: *help*
442 | Usage: *${prefix}menu* angka_index
443 |
444 | 3. *${prefix}status*
445 | Menampilkan status bot.
446 | Aliases: *stats*
447 | Usage: *${prefix}status*
448 |
449 | 4. *${prefix}listblock*
450 | Cek nomor yang diblokir.
451 | Aliases: -
452 | Usage: *${prefix}listblock*
453 |
454 | 5. *${prefix}ping*
455 | Cek speed bot.
456 | Aliases: *p*
457 | Usage: *${prefix}ping*
458 |
459 | 6. *${prefix}delete*
460 | Hapus pesan dari bot.
461 | Aliases: *del*
462 | Usage: Reply pesan yang dihapus dengan caption *${prefix}delete*.
463 |
464 | 7. *${prefix}report*
465 | Laporkan bug ke dev.
466 | Aliases: -
467 | Usage: *${prefix}report* pesan
468 |
469 | 8. *${prefix}tos*
470 | Syarat dan ketentuan. (TOS)
471 | Aliases: -
472 | Usage: *${prefix}tos*
473 |
474 | 9. *${prefix}join*
475 | Join grup via link.
476 | Aliases: -
477 | Usage: *${prefix}join* link_group
478 |
479 | 10. *${prefix}ownerbot*
480 | Mengirim kontak owner.
481 | Aliases: -
482 | Usage: *${prefix}ownerbot*
483 |
484 | 11. *${prefix}getpic*
485 | Mengirim foto profil user.
486 | Aliases: -
487 | Usage: *${prefix}getpic* @user/62812xxxxxxxx
488 |
489 | 12. *${prefix}premiumcheck*
490 | Cek masa aktif premium.
491 | Aliases: *cekpremium*
492 | Usage: *${prefix}premiumcheck*
493 |
494 | 13. *${prefix}premiumlist*
495 | Cek list user premium.
496 | Aliases: *listpremium*
497 | Usage: *${prefix}premiumlist*
498 |
499 | 14. *${prefix}limit*
500 | Cek limit kamu.
501 | Aliases: -
502 | Usage: *${prefix}limit*
503 |
504 | 15. *${prefix}serial*
505 | Cek biodata menggunakan serial.
506 | Aliases: -
507 | Usage: *${prefix}serial* serial
508 |
509 | 16. *${prefix}runtime*
510 | Cek runtime host.
511 | Aliases: -
512 | Usage: *${prefix}runtime*
513 |
514 | 17. *${prefix}unregister*
515 | Unregister akun.
516 | Aliases: *unreg*
517 | Usage: *${prefix}unregister*
518 |
519 | _Index of [2]_
520 | `
521 | }
522 |
523 | exports.menuMisc = () => {
524 | return `
525 | *── 「 MISC 」 ──*
526 |
527 | 1. *${prefix}say*
528 | Bot akan mengulang pesan mu.
529 | Aliases: -
530 | Usage: *${prefix}say* teks
531 |
532 | 2. *${prefix}tts*
533 | Membuat Text to Speech. Kalian perlu kode bahasa setiap menggunakan, cek di sini https://id.wikipedia.org/wiki/Daftar_bahasa_menurut_ISO_639-2
534 | Aliases: -
535 | Usage: *${prefix}tts* kode_bahasa | teks
536 |
537 | 3. *${prefix}afk*
538 | Set akun kamu ke mode AFK, aku akan mengirim pesan ke orang yang me-mention kamu.
539 | Aliases: -
540 | Usage: *${prefix}afk* alasan. Kirim pesan ke grup untuk menonaktifkan mode AFK.
541 |
542 | 4. *${prefix}math*
543 | Kalkulator.
544 | * = Perkalian
545 | + = Pertambahan
546 | - = Pengurangan
547 | / = Pembagian
548 | Aliases: -
549 | Usage: *${prefix}math* 12*12
550 |
551 | 5. *${prefix}reminder*
552 | Pengingat.
553 | *s* - detik
554 | *m* - menit
555 | *h* - jam
556 | *d* - hari
557 | Aliases: -
558 | Usage: *${prefix}reminder* 10s | pesan_pengingat
559 |
560 | 6. *${prefix}imagetourl*
561 | Image uploader.
562 | Aliases: *imgtourl*
563 | Usage: Kirim gambar dengan caption *${prefix}imagetourl* atau reply gambar dengan caption *${prefix}imagetourl*.
564 |
565 | 7. *${prefix}genshininfo*
566 | Kirim info karakter Genshin Impact.
567 | Aliases: *genshin*
568 | Usage: *${prefix}genshininfo* nama_karakter
569 |
570 | 8. *${prefix}translate*
571 | Terjemahkan teks.
572 | Aliases: *trans*
573 | Usage: *${prefix}translate* teks | kode_bahasa, bisa menggunakan reply juga
574 |
575 | 9. *${prefix}tomp3*
576 | Format video ke MP3.
577 | Aliases: -
578 | Usage: Kirim video dengan caption *${prefix}tomp3* atau reply video dengan caption *${prefix}tomp3*.
579 |
580 | 10. *${prefix}bass*
581 | Bass boost, bikin telinga sakit.
582 | Aliases: -
583 | Usage: Reply audio/voice dengan caption *${prefix}bass* tingkat_dB.
584 |
585 | 11. *${prefix}nightcore*
586 | Membuat efek nightcore dari audio.
587 | Aliases: -
588 | Usage: Reply audio/voice dengan caption *${prefix}nightcore*
589 |
590 | 12. *${prefix}google*
591 | Mencari via Google.
592 | Aliases: *googlesearch*
593 | Usage: *${prefix}google* query
594 |
595 | 13. *${prefix}toptt*
596 | Buat audio PTT.
597 | Aliases: *ptt*
598 | Usage: Reply audio/voice dengan caption *${prefix}toptt*
599 |
600 | 14. *${prefix}quizizz*
601 | Mengambil Data Quizizz
602 | Aliases: *quizizz hack*
603 | Usage: *${prefix}quizizz* query
604 |
605 |
606 | _Index of [3]_
607 | `
608 | }
609 |
610 | exports.menuSticker = () => {
611 | return `
612 | *── 「 STICKER 」 ──*
613 |
614 | 1. *${prefix}sticker*
615 | Membuat stiker dari gambar yang dikirim atau di-reply.
616 | Aliases: *stiker*
617 | Usage: Kirim gambar dengan caption *${prefix}sticker* atau reply gambar dengan caption *${prefix}sticker*.
618 |
619 | 2. *${prefix}stickergif*
620 | Membuat stiker dari video MP4 atau GIF yang dikirim atau di-reply.
621 | Aliases: *stikergif*
622 | Usage: Kirim video/GIF dengan caption *${prefix}stickergif* atau reply video/GIF dengan caption *${prefix}stickergif*.
623 |
624 | 3. *${prefix}stickertoimg*
625 | Konversi stiker ke foto.
626 | Aliases: *stikertoimg toimg*
627 | Usage: Reply sticker dengan caption *${prefix}stickertoimg*.
628 |
629 | 4. *${prefix}stickerwm*
630 | Buat stiker dengan WM.
631 | Aliases: *stcwm*
632 | Usage: Kirim gambar dengan caption *${prefix}stickerwm* pack_name | author_name atau reply gambar dengan caption *${prefix}stickerwm* pack_name | author_name.
633 |
634 | 5. *${prefix}stickermeme*
635 | Buat sticker meme.
636 | Aliases: *stcmeme*
637 | Usage: Kirim gambar dengan caption *${prefix}stickermeme* teks_atas | teks_bawah atau reply gambar dengan caption *${prefix}stickermeme* teks_atas | teks_bawah.
638 |
639 | 6. *${prefix}takestick*
640 | Merubah watermark sticker.
641 | Aliases: -
642 | Usage: Reply stiker dengan caption *${prefix}takestick* pack_name | author_name
643 |
644 | 7. *${prefix}stickernobg*
645 | Membuat stiker tanpa background.
646 | Aliases: *take*
647 | Usage: Kirim gambar dengan caption *${prefix}stickernobg* atau reply gambar dengan caption *${prefix}stickernobg*
648 |
649 |
650 | _Index of [4]_
651 | `
652 | }
653 |
654 | exports.menuWeeaboo = () => {
655 | return `
656 | *── 「 WEEABOO 」 ──*
657 |
658 | 1. *${prefix}neko*
659 | Mengirim foto neko girl.
660 | Aliases: -
661 | Usage: *${prefix}neko*
662 |
663 | 2. *${prefix}wallpaper*
664 | Mengirim wallpaper anime.
665 | Aliases: *wp*
666 | Usage: *${prefix}wallpaper*
667 |
668 | 3. *${prefix}kemono*
669 | Mengirim foto kemonomimi girl.
670 | Aliases: -
671 | Usage: *${prefix}kemono*
672 |
673 | 4. *${prefix}wait*
674 | Mencari source anime dari screenshot scene.
675 | Aliases: -
676 | Usage: Kirim screenshot dengan caption *${prefix}wait* atau reply screenshot dengan caption *${prefix}wait*.
677 |
678 | 5. *${prefix}source*
679 | Mencari source dari panel doujin, ilustrasi, dan gambar yang berhubungan dengan anime.
680 | Aliases: *sauce*
681 | Usage: Kirim gambar dengan caption *${prefix}source* atau reply gambar dengan caption *${prefix}source*.
682 |
683 | 6. *${prefix}waifu*
684 | Mengirim random foto waifu.
685 | Aliases: -
686 | Usage: *${prefix}waifu*
687 |
688 | _Index of [5]_
689 | `
690 | }
691 |
692 | exports.menuFun = () => {
693 | return `
694 | *── 「 FUN 」 ──*
695 |
696 | 1. *${prefix}triggered*
697 | Membuat efek triggered.
698 | Aliases: -
699 | Usage: Kirim gambar dengan caption *${prefix}triggered* atau reply pesan orang dengan *${prefix}triggered*.
700 |
701 | 2. *${prefix}kiss*
702 | Kiss someone ( ͡° ͜ʖ ͡°).
703 | Aliases: -
704 | Usage: Kirim gambar dengan caption *${prefix}kiss* atau reply gambar dengan *${prefix}kiss*.
705 |
706 | 3. *${prefix}profile*
707 | Cek profile.
708 | Aliases: *me*
709 | Usage: *${prefix}profile*
710 |
711 | 4. *${prefix}trash*
712 | Trash?
713 | Aliases: -
714 | Usage: *${prefix}trash*
715 |
716 | 5. *${prefix}hitler*
717 | Worse than hitler.
718 | Aliases: -
719 | Usage: *${prefix}hitler*
720 |
721 | _Index of [6]_
722 | `
723 | }
724 |
725 | exports.menuModeration = () => {
726 | return `
727 | *── 「 MODERATION 」 ──*
728 |
729 | 1. *${prefix}add*
730 | Menambah user ke dalam group.
731 | Aliases: -
732 | Usage: *${prefix}add* 628xxxxxxxxxx
733 |
734 | 2. *${prefix}kick*
735 | Mengeluarkan member dari grup.
736 | Aliases: -
737 | Usage: *${prefix}kick* @member1
738 |
739 | 3. *${prefix}promote*
740 | Promote member menjadi admin.
741 | Aliases: -
742 | Usage: *${prefix}promote* @member1
743 |
744 | 4. *${prefix}demote*
745 | Demote member dari admin.
746 | Aliases: -
747 | Usage: *${prefix}demote* @member1
748 |
749 | 5. *${prefix}leave*
750 | Bot akan meninggalkan grup.
751 | Aliases: -
752 | Usage: *${prefix}leave*
753 |
754 | 6. *${prefix}everyone*
755 | Mention semua member group.
756 | Aliases: -
757 | Usage: *${prefix}everyone*
758 |
759 | 7. *${prefix}groupicon*
760 | Mengganti icon grup.
761 | Aliases: -
762 | Usage: Kirim gambar dengan caption *${prefix}groupicon* atau reply gambar dengan caption *${prefix}groupicon*.
763 |
764 | 8. *${prefix}antilink*
765 | Mematikan/menyalakan fitur anti-group link.
766 | Aliases: -
767 | Usage: *${prefix}antilink* enable/disable
768 |
769 | 9. *${prefix}welcome*
770 | Mematikan/menyalakan fitur welcome di grup agar menyambut setiap kedatangan member.
771 | Aliases: -
772 | Usage: *${prefix}welcome* enable/disable
773 |
774 | 10. *${prefix}autosticker*
775 | Mematikan/menyalakan fitur auto-stiker. Setiap foto yang dikirim akan selalu diubah ke stiker.
776 | Aliases: *autostiker autostik*
777 | Usage: *${prefix}autostiker* enable/disable
778 |
779 | 11. *${prefix}antinsfw*
780 | Mematikan/menyalakan fitur anti-NSFW link.
781 | Aliases: -
782 | Usage: *${prefix}antinsfw* enable/disable
783 |
784 | 12. *${prefix}mutegc*
785 | Set group hanya admin yang bisa mengirim pesan.
786 | Aliases: -
787 | Usage: *${prefix}mutegc* enabled/disable
788 |
789 | 13. *${prefix}grouplink*
790 | Melihat invite link grup.
791 | Aliases: -
792 | Usage: *${prefix}grouplink*
793 |
794 | 14. *${prefix}revoke*
795 | Revoke invite link grup.
796 | Aliases: -
797 | Usage: *${prefix}revoke*
798 |
799 | 15. *${prefix}leveling*
800 | Mematikan/menyalakan fitur leveling.
801 | Aliases: -
802 | Usage: *${prefix}leveling* enable/disable
803 |
804 | 16. *${prefix}badwords*
805 | Setting fitur anti-bad word.
806 | Aliases: *badword*
807 | Usage: *${prefix}badwords* enable/disable atau add/remove untuk menambahkan/menghapus kata kasar.
808 |
809 |
810 | _Index of [7]_
811 | `
812 | }
813 |
814 | exports.menuOwner = () => {
815 | return `
816 | *── 「 OWNER 」 ──*
817 |
818 | 1. *${prefix}bc*
819 | Membuat broadcast.
820 | Aliases: -
821 | Usage: *${prefix}bc* teks
822 |
823 | 2. *${prefix}clearall*
824 | Menghapus semua chat di akun bot.
825 | Aliases: -
826 | Usage: *${prefix}clearall*
827 |
828 | 3. *${prefix}getses*
829 | Mengambil screenshot sesi dari akun bot.
830 | Aliases: -
831 | Usage: *${prefix}getses*
832 |
833 | 4. *${prefix}ban*
834 | Menambah/menghapus user yang diban.
835 | Aliases: -
836 | Usage: *${prefix}ban* add/del @user/62812xxxxxxxx
837 |
838 | 5. *${prefix}leaveall*
839 | Keluar dari semua grup.
840 | Aliases: -
841 | Usage: *${prefix}leaveall*
842 |
843 | 6. *${prefix}eval*
844 | Evaluate kode JavaScript.
845 | Aliases: *ev*
846 | Usage: *${prefix}eval*
847 |
848 | 7. *${prefix}shutdown*
849 | Men-shutdown bot.
850 | Aliases: -
851 | Usage: *${prefix}shutdown*
852 |
853 | 8. *${prefix}premium*
854 | Menambah/menghapus user premium.
855 | *s* - detik
856 | *m* - menit
857 | *h* - jam
858 | *d* - hari
859 | Aliases: -
860 | Usage: *${prefix}premium* add/del @user/62812xxxxxxxx 30d
861 |
862 | 9. *${prefix}setstatus*
863 | Mengganti status about me.
864 | Aliases: *setstats setstat*
865 | Usage: *${prefix}status* teks
866 |
867 | 10. *${prefix}serial*
868 | Cek pendaftaran akun via serial.
869 | Aliases: -
870 | Usage: *${prefix}serial* serial_user
871 |
872 | 11. *${prefix}exif*
873 | Atur WM stiker bot.
874 | Aliases: -
875 | Usage: *${prefix}exif* pack_name | author_name
876 |
877 | 12. *${prefix}mute*
878 | Mute semua user.
879 | Aliases: -
880 | Usage: Gunakan *${prefix}mute* untuk mute dan gunakan *${prefix}mute* kembali untuk unmute.
881 |
882 | 13. *${prefix}setname*
883 | Mengganti username bot. Maksimal 25 huruf.
884 | Aliases: -
885 | Usage: *${prefix}name* username_baru
886 |
887 | 14. *${prefix}block*
888 | Blok user.
889 | Aliases: *blok*
890 | Usage: *${prefix}block* @user/62812xxxxxxxx
891 |
892 | 15. *${prefix}unblock*
893 | Unblok user.
894 | Aliases: *unblok*
895 | Usage: *${prefix}unblock* @user/62812xxxxxxxx
896 |
897 | 16. *${prefix}xp*
898 | Menambahkan XP ke user.
899 | Aliases: -
900 | Usage: *${prefix}xp* @user jumlah_xp
901 |
902 | _Index of [8]_
903 | `
904 | }
905 |
906 | exports.menuLeveling = () => {
907 | return `
908 | *── 「 LEVELING 」 ──*
909 |
910 | 1. *${prefix}level*
911 | Untuk melihat level kamu.
912 | Aliases: -
913 | Usage: *${prefix}level*
914 |
915 | 2. *${prefix}leaderboard*
916 | Untuk melihat leaderboard.
917 | Aliaases: -
918 | Usage: *${prefix}leaderboard*
919 |
920 | _Index of [9]_
921 | `
922 | }
923 |
924 | exports.menuAi = () => {
925 | return `
926 | *── 「 AI 」 ──*
927 |
928 | 1. *${prefix}ai*
929 | Implementasi untuk ChatGPT 3.5
930 | Aliases: -
931 | Usage: *${prefix}ai* pertanyaan
932 |
933 | 2. *${prefix}image*
934 | Membuat gambar dari prompt/kata kunci.
935 | Aliases: *img*
936 | Usage: *${prefix}image* prompt
937 |
938 | _Index of [10]_
939 | `
940 | }
941 |
942 | exports.rules = () => {
943 | return `
944 | *── 「 RULES 」 ──*
945 |
946 | 1. Jangan spam bot.
947 | Sanksi: *WARN/SOFT BLOCK*
948 |
949 | 2. Jangan telepon bot.
950 | Sanksi: *SOFT BLOCK*
951 |
952 | 3. Jangan mengeksploitasi bot.
953 | Sanksi: *PERMANENT BLOCK*
954 |
955 | Jika sudah dipahami rules-nya, silakan ketik *${prefix}menu* untuk memulai!
956 | `
957 | }
958 |
959 | // Dimohon untuk owner/hoster jangan mengedit ini, terima kasih.
960 | exports.tos = (ownerNumber) => {
961 | return `
962 | *── 「 TERMS OF SERVICE 」 ──*
963 |
964 | Bot ini merupakan open-source bot dengan nama asli BocchiBot yang tersedia di GitHub secara gratis.
965 | Owner/hoster dari bot ini terlepas dari tanggung jawab dan pengawasan developer (Slavyan).
966 | Owner/hoster boleh menjiplak, menambahkan, menghapus, mengganti source code dengan catatan *tidak memperjualbelikannya* dalam bentuk apapun.
967 | Apabila terjadi sebuah error, orang yang pertama yang harus kalian hubungi ialah owner/hoster.
968 |
969 | Jika kalian ingin berkontribusi dalam projek ini, silakan kunjungi:
970 | https://github.com/SlavyanDesu/BocchiBot
971 |
972 | Contact person:
973 | wa.me/${ownerNumber.replace('@c.us', '')} (Owner/hoster)
974 |
975 | Regards,
976 | Slavyan.
977 | `
978 | }
979 |
--------------------------------------------------------------------------------
/message/text/lang/index.js:
--------------------------------------------------------------------------------
1 | exports.ind = require('./ind')
2 | exports.eng = require('./eng')
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bocchibot",
3 | "version": "1.5.0",
4 | "description": "BocchiBot is a multipurpose WhatsApp bot.",
5 | "main": "index.js",
6 | "type": "commonjs",
7 | "scripts": {
8 | "start": "node index.js"
9 | },
10 | "author": "SlavyanDesu",
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/SlavyanDesu/BocchiBot.git"
14 | },
15 | "bugs": {
16 | "url": "https://github.com/SlavyanDesu/BocchiBot/issues"
17 | },
18 | "homepage": "https://github.com/SlavyanDesu/BocchiBot",
19 | "license": "MIT",
20 | "dependencies": {
21 | "@open-wa/wa-automate": "^4.65.0",
22 | "@vitalets/google-translate-api": "^9.1.0",
23 | "await-exec": "^0.1.2",
24 | "bad-words": "^3.0.4",
25 | "canvacord": "^5.4.8",
26 | "chalk": "4.1.2",
27 | "figlet": "^1.6.0",
28 | "file-type": "16.5.4",
29 | "fluent-ffmpeg": "^2.1.2",
30 | "form-data": "^4.0.0",
31 | "fs-extra": "^11.1.1",
32 | "genshin": "^1.2.4",
33 | "google-it": "^1.6.4",
34 | "is-porn": "^0.9.0",
35 | "mathjs": "^11.8.0",
36 | "moment-timezone": "^0.5.43",
37 | "ms": "^2.1.3",
38 | "nekos.life": "^3.0.0",
39 | "node-cron": "^3.0.2",
40 | "node-fetch": "2.6.7",
41 | "node-gtts": "^2.0.2",
42 | "node-tesseract-ocr": "^2.2.1",
43 | "openai": "^3.2.1",
44 | "parse-ms": "2.1.0",
45 | "sagiri": "^3.4.0",
46 | "video-url-link": "^0.1.5",
47 | "ytdl-core": "^4.11.4"
48 | },
49 | "devDependencies": {
50 | "eslint": "^8.38.0"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tools/fetcher.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-async-promise-executor */
2 | const fs = require('fs-extra')
3 | const FormData = require('form-data')
4 | const FileType = require('file-type')
5 | const fetch = require('node-fetch')
6 |
7 | /**
8 | * Fetch JSON from URL.
9 | * @param {string} url
10 | * @param {object} [options]
11 | * @returns {Promise}
12 | */
13 | const fetchJson = (url, options) => {
14 | return new Promise(async (resolve, reject) => {
15 | try {
16 | const response = await fetch(url, options)
17 | const json = await response.json()
18 | return resolve(json)
19 | } catch (err) {
20 | return reject(err)
21 | }
22 | })
23 | }
24 |
25 | /**
26 | * Upload images to telegra.ph server.
27 | * @param {Buffer} buffData
28 | * @param {string} fileName
29 | * @returns {Promise}
30 | */
31 | const uploadImages = (buffData, fileName) => {
32 | return new Promise(async (resolve, reject) => {
33 | const { fromBuffer } = FileType
34 | const type = await fromBuffer(buffData)
35 | const filePath = `temp/${fileName}.${type.ext}`
36 | fs.writeFile(filePath, buffData, { encoding: 'base64' }, (err) => {
37 | if (err) reject(err)
38 | const fileData = fs.readFileSync(filePath)
39 | const form = new FormData()
40 | form.append('file', fileData, `${fileName}.${type.ext}`)
41 | fetch('https://telegra.ph/upload', {
42 | method: 'POST',
43 | body: form
44 | })
45 | .then((response) => response.json())
46 | .then((result) => {
47 | if (result.error) reject(result.error)
48 | resolve('https://telegra.ph' + result[0].src)
49 | })
50 | .then(() => fs.unlinkSync(filePath))
51 | .catch((err) => reject(err))
52 | })
53 | })
54 | }
55 |
56 | module.exports = {
57 | fetchJson,
58 | uploadImages
59 | }
--------------------------------------------------------------------------------
/tools/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-vars */
2 | const chalk = require('chalk')
3 | const crypto = require('crypto')
4 | const moment = require('moment-timezone')
5 | moment.tz.setDefault('Asia/Jakarta').locale('id')
6 |
7 | /**
8 | * Get text with color.
9 | * @param {string} text
10 | * @param {string} [color]
11 | */
12 | const color = (text, color) => {
13 | return !color ? chalk.green(text) : chalk.keyword(color)(text)
14 | }
15 |
16 | /**
17 | * Create serial ID.
18 | * @param {number} size
19 | * @returns {string}
20 | */
21 | const createSerial = (size) => {
22 | return crypto.randomBytes(size).toString('hex').slice(0, size)
23 | }
24 |
25 | /**
26 | * URL validator.
27 | * @param {string} url
28 | * @returns {boolean}
29 | */
30 | const isUrl = (url) => {
31 | return url.match(new RegExp(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)/gi))
32 | }
33 |
34 | /**
35 | * Get time duration.
36 | * @param {Date} timestamp
37 | * @param {Date} now
38 | * @returns {number}
39 | */
40 | const processTime = (timestamp, now) => {
41 | return moment.duration(now - moment(timestamp * 1000)).asSeconds()
42 | }
43 |
44 | const chromeArgs = [
45 | '--aggressive-cache-discard',
46 | '--aggressive-tab-discard',
47 | '--disable-accelerated-2d-canvas',
48 | '--disable-application-cache',
49 | '--disable-cache',
50 | '--disable-dev-shm-usage',
51 | '--disable-gpu',
52 | '--disable-offline-load-stale-cache',
53 | '--disable-setuid-sandbox',
54 | '--disable-setuid-sandbox',
55 | '--disk-cache-size=0',
56 | '--ignore-certificate-errors',
57 | '--no-first-run',
58 | '--no-sandbox',
59 | '--no-zygote'
60 | ]
61 |
62 | /**
63 | * Client options.
64 | * @param {Function} start
65 | * @returns {options}
66 | */
67 | const options = (start) => {
68 | const options = {
69 | sessionId: 'BocchiBot',
70 | headless: "new",
71 | qrTimeout: 0,
72 | authTimeout: 0,
73 | restartOnCrash: start,
74 | cacheEnabled: false,
75 | multiDevice: true,
76 | useChrome: true,
77 | killProcessOnBrowserClose: true,
78 | throwErrorOnTosBlock: false,
79 | // chromiumArgs: chromeArgs
80 | }
81 | return options
82 | }
83 |
84 | // Anti-spam
85 | const usedCommandRecently = new Set()
86 |
87 | /**
88 | * Check is number filtered.
89 | * @param {string} from
90 | * @returns {boolean}
91 | */
92 | const isFiltered = (from) => {
93 | return !!usedCommandRecently.has(from)
94 | }
95 |
96 | /**
97 | * Add filter to number.
98 | * @param {string} from
99 | */
100 | const addFilter = (from) => {
101 | usedCommandRecently.add(from)
102 | setTimeout(() => {
103 | return usedCommandRecently.delete(from)
104 | }, 5000)
105 | }
106 |
107 | module.exports = {
108 | msgFilter: {
109 | isFiltered,
110 | addFilter
111 | },
112 | color,
113 | isUrl,
114 | processTime,
115 | options,
116 | createSerial
117 | }
118 |
--------------------------------------------------------------------------------