├── .dockerignore
├── .eslintrc.yml
├── .github
├── FUNDING.yml
├── dependabot.yml
└── workflows
│ └── codeql-analysis.yml
├── .gitignore
├── HandleMsg.js
├── LICENSE
├── README.md
├── bin
└── ffmpeg.exe
├── checkapinobg.js
├── data
└── .none
├── ecosystem.config.cjs
├── index.js
├── lib
├── api.js
├── canvas.js
├── cekResi.js
├── index.js
├── kataKotor.js
├── list.js
├── location.js
├── menu.js
├── note.js
├── resep.js
├── schedule.js
├── scraper.js
├── sewa.js
├── shortener.js
└── tebak.js
├── media
└── tes.txt
├── package.json
├── patches
└── fluent-ffmpeg+2.1.2.patch
├── restart.cmd
├── settings
├── api.json.example
├── katakasar.json
├── nsfwquery.json
└── setting.json
├── src
├── font
│ ├── ChakraPetch-Bold.ttf
│ └── ChakraPetch-Regular.ttf
├── json
│ ├── genshinbuild.json
│ └── surah.json
├── mov
│ └── wasted.mov
├── png
│ ├── ava.png
│ ├── bg.png
│ ├── bgnight.png
│ └── group.png
├── sfx
│ ├── astaghfirullah.mp3
│ ├── balebale.mp3
│ ├── callambulance.mp3
│ ├── headshot.mp3
│ ├── kekw.mp3
│ ├── kuinginmarah.mp3
│ ├── kumenangis.mp3
│ ├── letsgo.mp3
│ ├── salam.mp3
│ ├── vacation.mp3
│ └── wtf.mp3
└── txt
│ ├── dare.txt
│ ├── skripsi.txt
│ └── truth.txt
└── utils
├── fetcher.js
├── index.js
├── options.js
└── resizeImage.js
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.eslintrc.yml:
--------------------------------------------------------------------------------
1 | env:
2 | browser: true
3 | es2021: true
4 | extends: 'eslint:recommended'
5 | parserOptions:
6 | ecmaVersion: 12
7 | sourceType: module
8 | rules: {}
9 | globals:
10 | LOCAL_DATE_OPTIONS: readonly
11 | isLolApiActive: writable
12 | readMore: readonly
13 | color: readonly
14 | simi: writable
15 | q3: readonly
16 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: ['https://saweria.co/dngda', 'https://trakteer.id/dngda'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "npm" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "daily"
12 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ main ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ main ]
20 | schedule:
21 | - cron: '27 1 * * 3'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'javascript' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
37 | # Learn more:
38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
39 |
40 | steps:
41 | - name: Checkout repository
42 | uses: actions/checkout@v2
43 |
44 | # Initializes the CodeQL tools for scanning.
45 | - name: Initialize CodeQL
46 | uses: github/codeql-action/init@v1
47 | with:
48 | languages: ${{ matrix.language }}
49 | # If you wish to specify custom queries, you can do so here or in a config file.
50 | # By default, queries listed here will override any specified in a config file.
51 | # Prefix the list here with "+" to use these queries and those in the config file.
52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
53 |
54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
55 | # If this step fails, then you should remove it and run the build manually (see below)
56 | - name: Autobuild
57 | uses: github/codeql-action/autobuild@v1
58 |
59 | # ℹ️ Command-line programs to run using the OS shell.
60 | # 📚 https://git.io/JvXDl
61 |
62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
63 | # and modify them (or add more) to build your code if your project
64 | # uses a compiled language
65 |
66 | #- run: |
67 | # make bootstrap
68 | # make release
69 |
70 | - name: Perform CodeQL Analysis
71 | uses: github/codeql-action/analyze@v1
72 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dempedency directory
2 | node_modules
3 | # Dot files
4 | .idea
5 | .node-persist
6 | # Log files
7 | debug.log
8 | # Session files
9 | *.data.json
10 | # Workspace files
11 | *.code-workspace
12 | # Lock files
13 | package-lock.json
14 | # Data files
15 | data/*
16 | media/*
17 | logs/*
18 | # Api files
19 | settings/api.json
20 |
21 | # managed
22 | **.data.json
23 | **.node-persist**
24 | # end managed
25 |
26 | # temp
27 | test*.js
28 | tmp
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | UNMAINTAINED - Multipurpose WhatsApp Bot using open-wa/wa-automate-nodejs library!
8 |
9 | Made with ❤️ by
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | ## Getting Started
24 |
25 | This project require NodeJS v12
26 |
27 | ### Install
28 | Clone this project
29 |
30 | ```bash
31 | > git clone https://github.com/dngda/bot-whatsapp
32 | > cd bot-whatsapp
33 | ```
34 |
35 | You need to install Libreoffice to use doctopdf command
36 |
37 | Install the dependencies:
38 |
39 | ```bash
40 | > npm install
41 | ```
42 | Change all apiKey on [this section](https://github.com/dngda/bot-whatsapp/blob/main/settings/api.json.example) then *rename to api.json*
43 |
44 | ### Usage
45 | Run the Whatsapp bot
46 |
47 | ```bash
48 | > npm start
49 | ```
50 |
51 | After running it you need to scan the QR
52 |
53 | ### Information
54 | - Change ownerNumber on [this section](https://github.com/dngda/bot-whatsapp/blob/main/settings/setting.json#L2)
55 | - Change groupLimit on [this section](https://github.com/dngda/bot-whatsapp/blob/main/settings/setting.json#L3)
56 | - Change memberLimit on [this section](https://github.com/dngda/bot-whatsapp/blob/main/settings/setting.json#L4)
57 | - Change prefix on [this section](https://github.com/dngda/bot-whatsapp/blob/main/settings/setting.json#L5)
58 | - Change menu on [this section](https://github.com/dngda/bot-whatsapp/blob/main/lib/menu.js#L34)
59 | - Add kata kasar on [this section](https://github.com/dngda/bot-whatsapp/blob/main/settings/katakasar.json)
60 | - Create Saweria account and get SaweriaOverlay on [this website](https://saweria.co)
61 |
62 | - Get Api NoBackground on [this website](https://www.remove.bg/)
63 | - Get Api LolHuman on [this website](https://lolhuman.herokuapp.com)
64 | - Get Api Fariaz on [this website](https://rest.farzain.com)
65 | - Get Api Genius on [this website](https://genius.com/developers)
66 | - Get Api Itech on [this website](https://api.i-tech.id)
67 | - Get Api Ocr on [this website](https://ocr.space/OCRAPI)
68 | ---
69 |
70 | ## Features
71 | Operasi kalkulator gunakan prefix (=)
72 | (cth: =10+2+4)
73 |
74 | Informasi
75 | - donate or donasi
76 | - ping or speed
77 | - owner
78 | - stat
79 |
80 | Converter
81 | - getimage or toimg
82 | -> Mengubah sticker menjadi gambar.
83 | - sticker or stiker or s
84 | -> Mengubah gambar/video menjadi sticker.
85 | - stickergiphy
86 | -> Mengubah url giphy menjadi sticker.
87 | - doctopdf or pdf
88 | -> Mengubah dokumen menjadi pdf.
89 | - qrcode or qr
90 | -> Membuat QRcode dari text.
91 | - tts or say
92 | -> Mengubah text menjadi suara Google.
93 | - shortlink
94 | -> Pemendek url menggunakan tinyurl.
95 | - translate
96 | -> Google translate text.
97 | - memefy
98 | -> Menambahkan text pada gambar.
99 | - tomp3
100 | -> Convert video ke audio.
101 | - hilih
102 | -> Mengubah text vokal menjadi huruf i.
103 | - ssweb
104 | -> Screenshot url website.
105 | - flip
106 | -> Balik gambar scr horizontal/vertikal.
107 |
108 | Downloader
109 | - tiktokmp3
110 | -> Download musik dari link tiktok.
111 | - tiktok
112 | -> Download tiktok tanpa watermark.
113 | - ytmp3
114 | -> Download mp3 dari link youtube.
115 | - ytmp4
116 | -> Download mp4 dari link youtube.
117 |
118 | Audio Converter
119 | -> Menambahkan efek suara pada audio.
120 | - nightcore
121 | - deepslow
122 | - samarkan
123 | - vibrato
124 | - earrape
125 | - reverse
126 | - robot
127 | - cf
128 | -> Custom complex filter (Expert user only)
129 |
130 | Islam
131 | - listsurah
132 | -> Daftar surah yang tersedia.
133 | - infosurah
134 | -> Info surah yang diinginkan.
135 | - jsholat
136 | -> Jadwal sholat sesuai daerah.
137 | - alaudio
138 | -> Audio dari surah yg diinginkan.
139 | - tafsir
140 | -> Tafsir surah yg diinginkan.
141 | - surah
142 | -> Menampilkan ayat dari surah yang diinginkan.
143 |
144 | Random
145 | -> Random berarti acak.
146 | - katabijak
147 | - skripsi
148 | - pantun
149 | - fakta
150 | - quote
151 | - anime
152 | - memes
153 |
154 | Search
155 | - pinterest or pin
156 | -> Search gambar dari pinterest.
157 | - gimages or gimg
158 | -> Search gambar dari Google.
159 | - whatanime
160 | -> Mencoba menebak anime dari gambar.
161 | - artinama
162 | -> Primbon arti nama, hanya hiburan.
163 | - sreddit
164 | -> Search gambar dari Subreddit.
165 | - lirik
166 | -> Search lirik lagu.
167 | - play
168 | -> Search lagu dari Youtube.
169 | - kbbi
170 | -> Search arti kata dalam KBBI.
171 | - yt
172 | -> Search Youtube.
173 |
174 | Hiburan
175 | - tebakgambar
176 | -> Main tebak gambar.
177 | - apakah
178 | -> Puja kerang ajaib!!!
179 | - sfx
180 | -> Mengirimkan audio yg tersedia.
181 | - ToD
182 | -> Group only. Truth or dare?
183 |
184 | Info
185 | - cekcovid
186 | -> Cek sebaran covid sesuai lokasi.
187 | - crjogja
188 | -> Radar cuaca lokasi Jogja.
189 | - cuaca
190 | -> Informasi cuaca sesuai daerah.
191 | - resi
192 | -> Cek resi barang sesuai kurir.
193 |
194 | Anti Toxic
195 | -> Group only. Anti kata kasar.
196 | - antikasar
197 | - klasemen
198 | - reset
199 |
200 | More Useful
201 | - tagall or alle
202 | -> Group only. Tag seluruh member.
203 | - join or sewa
204 | -> Sewa bot untuk join group kalau slot tersedia.
205 | - remind
206 | -> Kirimkan pesan ulang sesuai waktu yg ditentukan.
207 | - list
208 | -> Membuat list atau daftar yg disimpan di bot.
209 | - note
210 | -> Membuat note atau catatan yg disimpan di bot.
211 | - bye
212 | -> Group only. Keluarkan bot.
213 | - del
214 | -> Hapus pesan bot.
215 |
216 |
217 | ---
218 |
219 | ## Troubleshooting
220 | Make sure all the necessary dependencies are installed: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
221 |
222 | Fix Stuck on linux, install google chrome stable:
223 | ```bash
224 | > wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
225 | > sudo apt install ./google-chrome-stable_current_amd64.deb
226 | ```
227 |
228 | ## Thanks to
229 | - [Open-WA-Automate](https://github.com/open-wa/wa-automate-nodejs)
230 | - [YogaSakti](https://github.com/YogaSakti/imageToSticker)
231 | - [MhankBarBar](https://github.com/MhankBarBar/whatsapp-bot)
232 | - [ArugaZ](https://github.com/ArugaZ/whatsapp-bot)
233 | - [Aziz0404](https://github.com/nuraziz0404/botwa)
234 | - [Gimenz](https://github.com/Gimenz)
235 |
--------------------------------------------------------------------------------
/bin/ffmpeg.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/bin/ffmpeg.exe
--------------------------------------------------------------------------------
/checkapinobg.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: SeroBot Team
3 | * @ Create Time: 2021-02-14 20:26:02
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-06-21 00:42:43
6 | * @ Description: Cek api bos
7 | */
8 |
9 | import request from 'request'
10 | import fs from 'fs'
11 | const { apiNoBg } = JSON.parse(fs.readFileSync('./settings/api.json'))
12 |
13 | apiNoBg.forEach(api => {
14 | request.get({
15 | url: 'https://api.remove.bg/v1.0/account',
16 | headers: {
17 | 'X-Api-Key': api
18 | },
19 | encoding: null
20 | }, function (_error, _response, body) {
21 | console.log(api, JSON.stringify(JSON.parse(body).data.attributes.api, null, 2))
22 | })
23 | })
--------------------------------------------------------------------------------
/data/.none:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/ecosystem.config.cjs:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line no-undef
2 | module.exports = {
3 | apps: [{
4 | name: "Bot WhatsApp",
5 | script: "./index.js",
6 | args: ["--color"],
7 | error_file: './logs/pm2/err.log',
8 | combine_logs: true,
9 | cron_restart: '30 */12 * * *'
10 | }]
11 | }
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: SeroBot Team
3 | * @ Create Time: 2021-01-02 20:31:13
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-08-05 16:43:46
6 | * @ Description:
7 | */
8 |
9 | import { createReadFileSync, initGlobalVariable } from './utils/index.js'
10 | import StealthPlugin from 'puppeteer-extra-plugin-stealth'
11 | import { create, Client, decryptMedia } from '@open-wa/wa-automate'
12 | import { canvas, schedule, sewa } from './lib/index.js'
13 | import chromeLauncher from 'chrome-launcher'
14 | import { scheduleJob } from 'node-schedule'
15 | import { HandleMsg } from './HandleMsg.js'
16 | import { spawn } from 'child_process'
17 | import options from './utils/options.js'
18 | import puppeteer from 'puppeteer-extra'
19 | import moment from 'moment-timezone'
20 | import PQueue from 'p-queue'
21 | import figlet from 'figlet'
22 | import fs from 'fs-extra'
23 | const path = chromeLauncher.Launcher.getInstallations()[0]
24 | const jobList = JSON.parse(createReadFileSync('./data/schedule.json'))
25 | const setting = JSON.parse(createReadFileSync('./settings/setting.json'))
26 | moment.tz.setDefault('Asia/Jakarta').locale('id')
27 | initGlobalVariable()
28 |
29 | let {
30 | ownerNumber,
31 | groupLimit,
32 | prefix
33 | } = setting
34 |
35 | const queue = new PQueue({ concurrency: 4, timeout: 3000, throwOnTimeout: true })
36 | queue.on('next', () => {
37 | if (queue.size > 0 || queue.pending > 0) console.log(color('[==>>]', 'red'), `In-process: ${queue.pending} In-queue: ${queue.size}`)
38 | })
39 |
40 | const start = async (client = new Client()) => {
41 | try {
42 | console.log(color(figlet.textSync('----------------', { horizontalLayout: 'default' })))
43 | console.log(color(figlet.textSync(' SeroBot', { font: 'Ghost', horizontalLayout: 'default' })))
44 | console.log(color(figlet.textSync('----------------', { horizontalLayout: 'default' })))
45 | console.log(color('[DEV]'), color('Danang', 'yellow'))
46 | console.log(color('[~>>]'), color('BOT Started!', 'green'))
47 | console.log(color('[>..]'), color('Owner Commands: /menuowner', 'green'))
48 | client.sendText(ownerNumber, `✅ Bot Started!`)
49 |
50 | puppeteer.use(StealthPlugin())
51 | const browser = await puppeteer.launch({
52 | executablePath: path,
53 | headless: true,
54 | args: [
55 | '--single-process',
56 | '--no-zygote',
57 | '--renderer-process-limit=1',
58 | '--no-first-run',
59 | '--no-sandbox',
60 | '--disable-setuid-sandbox',
61 | '--ignore-certificate-errors'
62 | ]
63 | }).catch(e => console.log(e))
64 |
65 | // process unread message
66 | client.getAllUnreadMessages().then(async unreadMessages => {
67 | for (let message of unreadMessages) {
68 | if (!message.isGroupMsg) await queue.add(() => HandleMsg(message, browser, client)).catch(err => {
69 | console.log((err.name === 'TimeoutError') ? `${color('[==>>]', 'red')} Error task process timeout!` : err)
70 | if (queue.isPaused) queue.start()
71 | })
72 | }
73 | })
74 |
75 | // ketika seseorang mengirim pesan
76 | client.onMessage(async message => {
77 | client.setPresence(true)
78 | client.getAmountOfLoadedMessages() // menghapus pesan cache jika sudah 3000 pesan.
79 | .then((msg) => {
80 | if (msg >= 3000) {
81 | console.log('[CLNT]', color(`Loaded Message Reach ${msg}, cuting message cache...`, 'yellow'))
82 | client.cutMsgCache()
83 | }
84 | })
85 | await queue.add(() => HandleMsg(message, browser, client)).catch(err => {
86 | console.log((err.name === 'TimeoutError') ? `${color('[==>>]', 'red')} Error task process timeout!` : err)
87 | if (queue.isPaused) queue.start()
88 | })
89 |
90 | if (queue.isPaused) queue.start()
91 | }).catch(err => {
92 | console.log(err)
93 | })
94 |
95 | // Load Scheduled Job
96 | // client, from, quotedId, content, date, isQuoted
97 |
98 | try {
99 | jobList.jobs.forEach(async (job) => {
100 | schedule.loadJob(client, job.from, job.quotedId, job.content, job.date, job.isQuoted).catch(e => console.log(e))
101 | })
102 | console.log(color('[LOGS]', 'grey'), `${jobList.jobs.length} ScheduledJobs Loaded`)
103 |
104 | // check sewa every 4 hours
105 | scheduleJob('0 */4 * * *', () => {
106 | console.log(color('[LOGS]', 'grey'), `Checking sewa expiring...`)
107 | sewa.checkExpireSewa(client).catch(e => console.log(e))
108 | })
109 |
110 | // Clear chat every day at 01:01
111 | scheduleJob('1 1 * * *', async () => {
112 | const chats = await client.getAllChats()
113 | client.sendText(ownerNumber, `Processed auto clear with ${chats.length} chat!`)
114 | let deleted = 0, cleared = 0
115 | for (let chat of chats) {
116 | if (!chat.isGroup && chat.id !== ownerNumber) {
117 | await client.deleteChat(chat.id)
118 | deleted += 1
119 | }
120 | if (chat.id === ownerNumber || chat.isGroup) {
121 | await client.clearChat(chat.id)
122 | cleared += 1
123 | }
124 | }
125 | client.sendText(ownerNumber, `Chat deleted : ${deleted}\nChat cleared : ${cleared}`)
126 | })
127 | } catch (e) {
128 | console.log(e)
129 | }
130 |
131 | // Listen saweria
132 | // sewa.listenSaweria(client, browser).catch(e => console.log(e))
133 |
134 | // ketika bot diinvite ke dalam group
135 | client.onAddedToGroup(async chat => {
136 | console.log(color('[==>>]', 'red'), `Someone is adding bot to group, lol~ groupId: ${chat.groupMetadata.id}`)
137 | client.getAllGroups().then((groups) => {
138 | // kondisi ketika batas group bot telah tercapai, ubah di file settings/setting.json
139 | console.log(color('[==>>]', 'red'), `Group total: ${groups.length}. groupLimit: ${groupLimit}`)
140 | if (groups.length > groupLimit) {
141 | console.log(color('[==>>]', 'red'), `So this is exceeding the group limit.`)
142 | client.sendText(chat.groupMetadata.id,
143 | `Mohon maaf, untuk mencegah overload, group pada bot dibatasi.\n` +
144 | `Total group: ${groups.length}/${groupLimit}\n` +
145 | `Chat /owner untuk sewa. harga 10k masa aktif 1 bulan.\n` //+
146 | // `Mau sewa otomatis? Buka link berikut:\n` +
147 | // `Saweria: https://saweria.co/dngda \n` +
148 | // `*Masukkan hanya link group kalian dalam kolom "Pesan" di website saweria*`
149 | )
150 | setTimeout(() => {
151 | client.leaveGroup(chat.groupMetadata.id)
152 | client.deleteChat(chat.groupMetadata.id)
153 | }, 3000)
154 | } else {
155 | client.simulateTyping(chat.groupMetadata.id, true).then(async () => {
156 | client.sendText(chat.groupMetadata.id, `Hai guys 👋 perkenalkan saya SeroBot. Untuk melihat perintah atau menu yang tersedia pada bot, kirim *${prefix}menu*. Tapi sebelumnya pahami dulu *${prefix}tnc*`)
157 | })
158 | }
159 | })
160 | })
161 |
162 | client.onIncomingCall(async call => {
163 | // ketika seseorang menelpon nomor bot
164 | if (!call.isGroup || !call.participants.length > 1) {
165 | console.log(color('[==>>]', 'red'), `Someone is calling bot, lol~ id: ${call.peerJid}`)
166 | client.sendText(call.peerJid, `⛔ Maaf tidak bisa menerima panggilan.\n🤖 Ini robot, bukan manusia. Maaf bot akan block otomatis!\n💬 Chat https://wa.me/${ownerNumber.replace('@c.us', '')}?text=Halo!%20Tolong%20buka%20block%20saya%20pada%20Serobot`)
167 | setTimeout(() => {
168 | client.contactBlock(call.peerJid)
169 | }, 3000)
170 | }
171 | })
172 |
173 | // Mempertahankan sesi agar tetap nyala
174 | client.onStateChanged((state) => {
175 | console.log(color('[~>>>]', 'red'), state)
176 | if (state === 'CONFLICT' || state === 'UNLAUNCHED') client.forceRefocus().then(() => queue.start())
177 | }).catch((err) => {
178 | console.log(err)
179 | })
180 |
181 | // ketika seseorang masuk/keluar dari group
182 | const host = await client.getHostNumber() + '@c.us'
183 | client.onGlobalParticipantsChanged(async event => {
184 | const welcome = JSON.parse(createReadFileSync('./data/welcome.json'))
185 | const isWelcome = welcome.includes(event.chat)
186 | const profile = await client.getProfilePicFromServer(event.who)
187 | const who = await client.getContact(event.who)
188 | const pushname = who.pushname || who.verifiedName || who.formattedName
189 | const chat = await client.getChatById(event.chat)
190 | const hasByProperty = Object.prototype.hasOwnProperty.call(event, 'by')
191 | // kondisi ketika seseorang diinvite/join group lewat link
192 | if (event.action === 'add' && event.who !== host && isWelcome && hasByProperty) {
193 | const welcomeData = await canvas.welcome(
194 | profile,
195 | chat.contact.profilePicThumbObj.eurl,
196 | pushname,
197 | chat.contact.name || chat.formattedTitle,
198 | chat.groupMetadata.participants.length).catch(err => console.log(color('[ERR>]', 'red'), err))
199 | await client.sendImage(event.chat, welcomeData, 'welcome.png', `Halo semua!👋✨ Anggota kita nambah satu nih\n-> @${event.who.replace(/@c\.us/g, '')}`)
200 |
201 | }
202 | // kondisi ketika seseorang dikick/keluar dari group
203 | if (event.action === 'remove' && event.who !== host && isWelcome) {
204 | await client.sendText(event.chat, `⚙ Eh ada yang keluar ya? Dadahhh ${pushname} 👋✨`)
205 | }
206 | // Saat host keluar
207 | if (event.action === 'remove' && event.who == host) {
208 | const ngegas = JSON.parse(createReadFileSync('./data/ngegaskick.json'))
209 | const antiLinkGroup = JSON.parse(createReadFileSync('./data/antilinkgroup.json'))
210 | const antiLink = JSON.parse(createReadFileSync('./data/antilink.json'))
211 | let _id = event.chat
212 | let pos = ngegas.indexOf(_id)
213 | if (pos !== -1) {
214 | ngegas.splice(pos, 1)
215 | fs.writeFileSync('./data/ngegaskick.json', JSON.stringify(ngegas))
216 | }
217 | let posi = welcome.indexOf(_id)
218 | if (posi !== -1) {
219 | welcome.splice(posi, 1)
220 | fs.writeFileSync('./data/welcome.json', JSON.stringify(welcome))
221 | }
222 | let posa = antiLinkGroup.indexOf(_id)
223 | if (posa !== -1) {
224 | antiLinkGroup.splice(posa, 1)
225 | fs.writeFileSync('./data/antilinkgroup.json', JSON.stringify(antiLinkGroup))
226 | }
227 | let posd = antiLink.indexOf(_id)
228 | if (posd !== -1) {
229 | antiLink.splice(posd, 1)
230 | fs.writeFileSync('./data/antilink.json', JSON.stringify(antiLink))
231 | }
232 | }
233 | }).catch(e => {
234 | console.log(color('[ERR>]', 'red'), e)
235 | })
236 |
237 | client.getPage().on('error', () => {
238 | client.sendText(ownerNumber, `⌛ Page Error! Server bot akan direstart!`)
239 | spawn('pm2 reload all')
240 | })
241 |
242 | client.onMessageDeleted(async message => {
243 | try {
244 | const antiDelete = JSON.parse(createReadFileSync('./data/antidelete.json'))
245 | const isAntiDelete = antiDelete.includes(message.from)
246 | if (message.author != host && isAntiDelete) {
247 | await client.sendTextWithMentions(message.from,
248 | `‼️〘 ANTI DELETE 〙‼️\n` +
249 | `${q3}Who :${q3} @${message.author.replace('@c.us', '')}\n` +
250 | `${q3}When :${q3} ${moment(message.t * 1000).format('DD MMM HH:mm:ss')}\n` +
251 | `${q3}Type :${q3} ${message.type.replace(/^\w/, (c) => c.toUpperCase())}` +
252 | `${message.type == 'chat' ? `\n${q3}Content :${q3}\n\n${message.body}` : ``}`
253 | )
254 | if (['image', 'video', 'ptt', 'audio', 'document'].includes(message.type)) {
255 | const mediaData = await decryptMedia(message)
256 | await client.sendFile(message.from, `data:${message.mimetype};base64,${mediaData.toString('base64')}`, '', message.caption)
257 | }
258 | if (message.type == 'sticker') {
259 | const mediaData = await decryptMedia(message)
260 | await client.sendImageAsSticker(message.from, mediaData, { pack: 'Anti delete by', author: 'SeroBot', keepScale: true })
261 | }
262 | }
263 | } catch (err) {
264 | console.log(color('[ERR>]', 'red'), err)
265 | }
266 | }).catch(e => {
267 | console.log(color('[ERR>]', 'red'), e)
268 | })
269 |
270 | } catch (err) {
271 | console.log(color('[ERR>]', 'red'), err)
272 | }
273 | }
274 |
275 | //create session
276 | create(options(true, start))
277 | .then(client => start(client))
278 | .catch(err => new Error(err))
279 |
--------------------------------------------------------------------------------
/lib/api.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: AirMineral Team
3 | * @ Create Time: 2021-05-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-07-19 11:01:14
6 | * @ Description: Tempat consume api
7 | */
8 |
9 | import axios from 'axios'
10 | import { load } from 'cheerio'
11 | import fs from 'fs-extra'
12 | import lodash from 'lodash'
13 | import { Agent } from 'https'
14 | const { sample } = lodash
15 | import yts from 'yt-search'
16 | const agent = new Agent({
17 | rejectUnauthorized: false
18 | })
19 | const { get } = axios
20 | const { readFileSync } = fs
21 |
22 | // eslint-disable-next-line no-unused-vars
23 | const { apiFarzain, apiItech, apiZeks, apiLol, apiGenius, apiOcr } = JSON.parse(readFileSync('./settings/api.json'))
24 |
25 | const quote = () => new Promise((resolve, reject) => {
26 | let slash = sample(["quotes", "quotes2", "quotes3"])
27 | get(`https://api.i-tech.id/tools/${slash}?key=${apiItech}`)
28 | .then((res) => {
29 | let text = ''
30 | let hasAuthorProperty = Object.prototype.hasOwnProperty.call(res.data, 'author')
31 | if (hasAuthorProperty) {
32 | text = `Author: ${res.data.author}\n\nQuote: ${res.data.result}`
33 | } else {
34 | text = res.data.result
35 | }
36 | resolve(text)
37 | })
38 | .catch((err) => {
39 | reject(err)
40 | })
41 | })
42 |
43 | const ytsearch = (query) => new Promise((resolve, reject) => {
44 | yts(query)
45 | .then((res) => {
46 | let data = res.all.slice(0, 5)
47 | resolve(data)
48 | }).catch((err) => {
49 | reject(err)
50 | })
51 | })
52 |
53 | const artinama = (nama) => new Promise((resolve, reject) => {
54 | get(`https://api.zeks.xyz/api/artinama?apikey=${apiZeks}&nama=${encodeURIComponent(nama)}`)
55 | .then((res) => {
56 | resolve(res.data.result)
57 | })
58 | .catch((err) => {
59 | reject(err)
60 | })
61 | })
62 |
63 | const lyric = (query) => new Promise((resolve, reject) => {
64 | get(`https://api.genius.com/search?q=${encodeURIComponent(query)}&access_token=${apiGenius}`)
65 | .then(res => {
66 | if (res.data.meta.status != 200) reject(res.data.meta.status + res.data.meta.message)
67 | const { hits } = res.data.response
68 | if (hits[0]) {
69 | get(hits[0].result.url).then(resu => {
70 | const $ = load(resu.data)
71 | let lyrics = $('div[class="lyrics"]').text().trim()
72 | if (!lyrics) {
73 | lyrics = ''
74 | $('div[class^="Lyrics__Container"]').each((i, elem) => {
75 | if ($(elem).text().length !== 0) {
76 | let snippet = $(elem).html()
77 | .replace(/
/g, '\n')
78 | .replace(/<(?!\s*br\s*\/?)[^>]+>/gi, '')
79 | lyrics += $('').html(snippet).text().trim() + '\n\n'
80 | }
81 | })
82 | }
83 | if (!lyrics) return resolve(`Error! Lirik tidak ditemukan.`)
84 | resolve(`${hits[0]?.result.full_title}\n\n${lyrics.trim()}`)
85 | }).catch(reject)
86 | } else {
87 | get(`https://scrap.terhambar.com/lirik?word=${encodeURIComponent(query)}`, { httpsAgent: agent })
88 | .then((res) => {
89 | resolve(res.data?.result?.lirik)
90 | })
91 | .catch((err) => {
92 | reject(err)
93 | })
94 | }
95 | }).catch(reject)
96 | })
97 |
98 | const cuaca = (daerah) => new Promise((resolve, reject) => {
99 | get(`https://rest.farzain.com/api/cuaca.php?id=${encodeURIComponent(daerah)}&apikey=${apiFarzain}`)
100 | .then((res) => {
101 | if (res.data.respon.cuaca == null) resolve('Maaf daerah kamu tidak tersedia')
102 | const text = `Cuaca di: ${res.data.respon.tempat}\n\nCuaca: ${res.data.respon.cuaca}\nAngin: ${res.data.respon.angin}\nDesk: ${res.data.respon.deskripsi}\nKelembapan: ${res.data.respon.kelembapan}\nSuhu: ${res.data.respon.suhu}\nUdara: ${res.data.respon.udara}`
103 | resolve(text)
104 | })
105 | .catch((err) => {
106 | reject(err)
107 | })
108 | })
109 |
110 | const tulis = (teks) => new Promise((resolve, reject) => {
111 | get(`https://arugaz.herokuapp.com/api/nulis?text=${encodeURIComponent(teks)}`)
112 | .then((res) => {
113 | resolve(`${res.data.result}`)
114 | })
115 | .catch((err) => {
116 | reject(err)
117 | })
118 | })
119 |
120 | /**
121 | *
122 | * @param {String} query
123 | *
124 | */
125 | const random = ['dankmemes', 'wholesomeanimemes', 'wholesomememes', 'AdviceAnimals', 'MemeEconomy', 'memes', 'terriblefacebookmemes', 'historymemes', 'okbuddyretard', 'nukedmemes']
126 | const sreddit = (reddit = false) => new Promise((resolve, reject) => {
127 | if (!reddit) reddit = sample(random)
128 | get('https://meme-api.herokuapp.com/gimme/' + reddit)
129 | .then((rest) => {
130 | resolve(rest.data)
131 | })
132 | .catch((err) => {
133 | reject(err)
134 | })
135 | })
136 |
137 | /**
138 | * create custom meme
139 | * @param {String} imageUrl
140 | * @param {String} topText
141 | * @param {String} bottomText
142 | */
143 | const memegen = (imageUrl, top, bottom) => {
144 | let topText = top.trim().replace(/\s/g, '_').replace(/\?/g, '~q').replace(/%/g, '~p').replace(/#/g, '~h').replace(/\//g, '~s')
145 | let bottomText = bottom.trim().replace(/\s/g, '_').replace(/\?/g, '~q').replace(/%/g, '~p').replace(/#/g, '~h').replace(/\//g, '~s')
146 | return `https://api.memegen.link/images/custom/${topText}/${bottomText}.png?background=${imageUrl}`
147 | }
148 |
149 | /**
150 | *
151 | * @param {String} query
152 | *
153 | */
154 | const pinterest = (wall) => new Promise((resolve, reject) => {
155 | get('https://fdciabdul.tech/api/pinterest?keyword=' + encodeURIComponent(wall), { httpsAgent: agent })
156 | .then((result) => {
157 | resolve(result.data)
158 | })
159 | .catch((err) => {
160 | reject(err)
161 | })
162 | })
163 |
164 | /**
165 | *
166 | * @param {String} query
167 | * @returns {String} msg
168 | */
169 | const simiLol = (inp) => new Promise((resolve, reject) => {
170 | get(`https://lolhuman.herokuapp.com/api/simi?apikey=${apiLol}&text=${encodeURIComponent(inp)}`)
171 | .then(res => {
172 | resolve(res.data.result)
173 | })
174 | .catch((e) => {
175 | reject(`SimiLol error: ` + e.message)
176 | })
177 | })
178 |
179 | /**
180 | *
181 | * @param {String} query
182 | * @returns {String} msg
183 | */
184 | const simiPais = (inp) => new Promise((resolve, reject) => {
185 | get(`https://pencarikode.xyz/api/simsimii?apikey=pais&text=${encodeURIComponent(inp)}`)
186 | .then(res => {
187 | resolve(res.data.result)
188 | })
189 | .catch((e) => {
190 | reject(`SimiPais error: ` + e.message)
191 | })
192 | })
193 |
194 | /**
195 | *
196 | * @param {String} query
197 | * @returns {String} msg
198 | */
199 | const simiZeks = (inp) => new Promise((resolve, reject) => {
200 | get(`https://api.zeks.xyz/api/simi?apikey=${apiZeks}&text=${encodeURIComponent(inp)}`)
201 | .then(res => {
202 | resolve(res.data.result)
203 | })
204 | .catch((e) => {
205 | reject(`SimiZeks error: ` + e.message)
206 | })
207 | })
208 |
209 | /**
210 | *
211 | * @param {String} query
212 | * @returns {String} msg
213 | */
214 | const simiSumi = (inp) => new Promise((resolve, reject) => {
215 | get(`https://simsumi.herokuapp.com/api?text=${encodeURIComponent(inp)}`)
216 | .then(res => {
217 | resolve(res.data.success)
218 | })
219 | .catch((e) => {
220 | reject(`Simisumi error: ` + e.message)
221 | })
222 | })
223 |
224 |
225 | /**
226 | *
227 | * @param {String} url
228 | * @returns {String} msg
229 | */
230 | const ocr = (url) => new Promise((resolve, reject) => {
231 | get(`https://api.ocr.space/parse/imageurl?apikey=${apiOcr}&url=${url}`)
232 | .then(res => {
233 | if (res.data?.IsErroredOnProcessing == true) resolve(res.data?.ErrorMessage)
234 | else resolve(res.data?.ParsedResults[0]?.ParsedText)
235 | })
236 | .catch(err => {
237 | reject(err)
238 | })
239 | })
240 |
241 | const ttdl = (url) => new Promise((resolve, reject) => {
242 | get(`https://hardianto-chan.herokuapp.com/api/download/tiktok?apikey=hardianto&url=${encodeURIComponent(url)}`)
243 | .then(res => {
244 | resolve(res.data)
245 | }).catch(reject)
246 | })
247 |
248 | export default {
249 | pinterest,
250 | artinama,
251 | ytsearch,
252 | simiPais,
253 | simiSumi,
254 | simiZeks,
255 | simiLol,
256 | sreddit,
257 | memegen,
258 | quote,
259 | cuaca,
260 | tulis,
261 | lyric,
262 | ttdl,
263 | ocr
264 | }
--------------------------------------------------------------------------------
/lib/canvas.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-async-promise-executor */
2 | /**
3 | * @ Author: SeroBot Team
4 | * @ Create Time: 2021-06-22 13:40:17
5 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
6 | * @ Modified time: 2021-07-12 12:40:14
7 | * @ Description:
8 | */
9 |
10 | import cvs from "canvas"
11 | const { createCanvas, registerFont, loadImage } = cvs
12 |
13 | const ttp = (text, color1 = `white`, color2 = null, strokeColor = `black`) => new Promise((resolve, reject) => {
14 | try {
15 | text = text.replace(/\s/g, '\n')
16 | const canvas = createCanvas(512, 512)
17 | const ctx = canvas.getContext('2d')
18 | let textData = text.split('\n')
19 |
20 | // Gabungkan kata yang pendek
21 | let s = 0
22 | do {
23 | s = textData.findIndex(n => {
24 | if (n.length < 5)
25 | return n
26 | })
27 | let isDepan = false
28 | if (s > 0 && s != textData.length - 1 && s != -1) {
29 | isDepan = textData[s - 1].length < textData[s + 1] ? true : false
30 | }
31 | if (s > 0 && s != textData.length - 1 && isDepan && s != -1) {
32 | const gabungan = `${textData[s - 1]} ${textData[s]}`
33 | textData.splice(s - 1, 2, gabungan)
34 | } else if (s != textData.length - 1 && !isDepan && s != -1) {
35 | const gabungan = `${textData[s]} ${textData[s + 1]}`
36 | textData.splice(s, 2, gabungan)
37 | } else if (s == textData.length - 1) {
38 | s = -1
39 | }
40 | } while (s != -1)
41 |
42 | // Pisahkan kata yang panjang
43 | let p = -1
44 | do {
45 | p = textData.findIndex(n => {
46 | if (n.length > 15)
47 | return n
48 | })
49 | if (p != -1) {
50 | const pisahan = textData[p].match(/.{1,14}/g)
51 | textData.splice(p, 1, pisahan[0], pisahan[1])
52 | }
53 | } while (p != -1)
54 |
55 | let posisiY = 256
56 | let longest = textData.reduce((a, b) => {
57 | return a.length > b.length ? a : b
58 | })
59 | let inpText = ctx.measureText(longest)
60 | let ukuranFont = 170 - inpText.width - (textData.length * 5)
61 | const lineHeight = inpText.emHeightAscent + ukuranFont
62 | posisiY = posisiY - (textData.length - 1) * lineHeight / 2
63 | ctx.font = `${ukuranFont}px Comic Sans MS`
64 | ctx.textAlign = 'center'
65 | ctx.textBaseline = 'middle'
66 | if (color2) {
67 | var grd = ctx.createLinearGradient(0, 0, 500, 0)
68 | grd.addColorStop(0, color1)
69 | grd.addColorStop(1, color2)
70 | ctx.fillStyle = grd
71 | } else {
72 | ctx.fillStyle = color1
73 | }
74 | ctx.strokeStyle = strokeColor
75 | ctx.lineWidth = 8
76 | textData.forEach((data, i) => {
77 | ctx.strokeText(data, 256, posisiY + (i * lineHeight), 500)
78 | ctx.fillText(data, 256, posisiY + (i * lineHeight), 500)
79 | })
80 |
81 | resolve(canvas.toBuffer())
82 | } catch (err) {
83 | reject(err)
84 | }
85 | })
86 |
87 | const welcome = (
88 | photoUrl = './src/png/ava.png',
89 | groupPhoto = './src/png/group.png',
90 | pushname = 'Unknown Name',
91 | groupName = 'Unknown Group',
92 | memberKe = 0
93 | ) => new Promise(async (resolve, reject) => {
94 | try {
95 | registerFont('./src/font/ChakraPetch-Regular.ttf', { family: 'Chakra Petch' })
96 | registerFont('./src/font/ChakraPetch-Bold.ttf', { family: 'Chakra Petch', weight: 'bold' })
97 |
98 | const canvas = createCanvas(1000, 500)
99 | const canvasGroup = createCanvas(160, 160)
100 | const canvasPhoto = createCanvas(250, 250)
101 | const ctx = canvas.getContext("2d")
102 | const ctxGroup = canvasGroup.getContext("2d")
103 | const ctxPhoto = canvasPhoto.getContext("2d")
104 |
105 | let bgPath = (new Date()).getHours() >= 18 || (new Date()).getHours() <= 5 ? './src/png/bgnight.png' : './src/png/bg.png'
106 | const bgImg = await loadImage(bgPath)
107 |
108 | const photoImg = await loadImage(photoUrl)
109 | const groupImg = await loadImage(groupPhoto)
110 | ctx.drawImage(bgImg, 0, 0)
111 |
112 | const groupImgSize = 160
113 | const size = 80, x = 80, y = 80
114 | ctxGroup.drawImage(groupImg, 0, 0, groupImgSize, groupImgSize)
115 | ctxGroup.globalCompositeOperation = "destination-in"
116 | ctxGroup.fillStyle = "#000"
117 | ctxGroup.beginPath()
118 | ctxGroup.moveTo(x + size * Math.cos(0), y + size * Math.sin(0))
119 | let side = 0
120 | for (side; side < 11; side++) {
121 | ctxGroup.lineTo(x + size * Math.cos(side * 2 * Math.PI / 10), y + size * Math.sin(side * 2 * Math.PI / 10))
122 | }
123 | ctxGroup.fill()
124 |
125 | const photoImgSize = 250
126 | const sizeP = 125, xP = 125, yP = 125
127 | ctxPhoto.drawImage(photoImg, 0, 0, photoImgSize, photoImgSize)
128 | ctxPhoto.globalCompositeOperation = "destination-in"
129 | ctxPhoto.fillStyle = "#000"
130 | ctxPhoto.beginPath()
131 | ctxPhoto.moveTo(xP + sizeP * Math.cos(0), yP + sizeP * Math.sin(0))
132 | let sideP = 0
133 | for (sideP; sideP < 11; sideP++) {
134 | ctxPhoto.lineTo(xP + sizeP * Math.cos(sideP * 2 * Math.PI / 10), yP + sizeP * Math.sin(sideP * 2 * Math.PI / 10))
135 | }
136 | ctxPhoto.fill()
137 |
138 | ctx.drawImage(canvasGroup, 90, 100)
139 | ctx.drawImage(canvasPhoto, 130, 145)
140 |
141 | ctx.textBaseline = 'middle'
142 | ctx.fillStyle = (new Date()).getHours() >= 18 || (new Date()).getHours() <= 5 ? 'white' : 'black'
143 | ctx.font = `bold 24px Chakra Petch`
144 | ctx.fillText(`Member #${memberKe}`, 430, 135)
145 | ctx.fillStyle = 'white'
146 | ctx.font = `bold 36px Chakra Petch`
147 | ctx.fillText(`Halo, ${pushname.trim().length > 17 ? pushname.trim().substring(0, 16) + '...' : pushname.trim()}`, 430, 190)
148 | ctx.font = `36px Chakra Petch`
149 | ctx.fillText(`Selamat datang di Group`, 430, 230)
150 | ctx.font = `bold 36px Chakra Petch`
151 | ctx.fillText(`${groupName.trim().length > 24 ? groupName.trim().substring(0, 23) + '...' : groupName.trim()}`, 430, 270)
152 | ctx.font = `30px Chakra Petch`
153 | ctx.fillStyle = (new Date()).getHours() >= 18 || (new Date()).getHours() <= 5 ? 'white' : 'black'
154 | ctx.fillText(`Jangan lupa perkenalan`, 430, 340)
155 | ctx.fillText(`dan baca aturan group!`, 430, 380)
156 |
157 | resolve(canvas.toDataURL())
158 | } catch (err) {
159 | reject(err)
160 | }
161 |
162 | })
163 | export default {
164 | welcome,
165 | ttp
166 | }
--------------------------------------------------------------------------------
/lib/cekResi.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: ArugaZ
3 | * @ Create Time: 2021-05-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-07-19 19:18:16
6 | * @ Description:
7 | */
8 |
9 | import axios from 'axios'
10 | import { Agent } from 'https'
11 |
12 | const agent = new Agent({
13 | rejectUnauthorized: false
14 | })
15 |
16 | /**
17 | * Get Resi Information
18 | *
19 | * @param {string} ekspedisi - nama ekpedisi
20 | * @param {string} resi - no / kode resi
21 | */
22 | const cekResi = (ekspedisi, resi) => new Promise((resolve, reject) => {
23 | axios.get(`https://api.terhambar.com/resi?resi=${resi}&kurir=${ekspedisi}`, { httpsAgent: agent })
24 | .then(res => {
25 | const result = res.data
26 | if (result.status.code != 200 && result.status.description != 'OK') return resolve(result.status.description)
27 | // eslint-disable-next-line camelcase
28 | const { result: { summary, details, delivery_status, manifest } } = result
29 | const manifestText = manifest.map(x => `⏰ ${x.manifest_date} ${x.manifest_time}\n ├ Status: ${x.manifest_description}\n └ Lokasi: ${x.city_name}`)
30 | const resultText = `
31 | 📦 Data Ekspedisi
32 | ├ ${summary.courier_name}
33 | ├ Nomor: ${summary.waybill_number}
34 | └ Dikirim Pada: ${details.waybill_date} ${details.waybill_time}
35 |
36 | 📮 Status Pengiriman
37 | └ ${delivery_status.status}
38 |
39 | 🚧 POD Detail\n
40 | ${manifestText.join('\n')}`
41 | resolve(resultText)
42 | }).catch((err) => {
43 | console.error(err)
44 | reject(err)
45 | })
46 | })
47 |
48 | export default cekResi
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | import getLocationData from './location.js'
2 | import urlShortener from './shortener.js'
3 | import cariKasar from './kataKotor.js'
4 | import schedule from './schedule.js'
5 | import scraper from './scraper.js'
6 | import cekResi from './cekResi.js'
7 | import canvas from './canvas.js'
8 | import tebak from './tebak.js'
9 | import menuId from './menu.js'
10 | import resep from './resep.js'
11 | import sewa from './sewa.js'
12 | import list from './list.js'
13 | import note from './note.js'
14 | import api from './api.js'
15 |
16 | export {
17 | getLocationData,
18 | urlShortener,
19 | cariKasar,
20 | schedule,
21 | cekResi,
22 | scraper,
23 | canvas,
24 | menuId,
25 | resep,
26 | tebak,
27 | sewa,
28 | list,
29 | note,
30 | api
31 | }
--------------------------------------------------------------------------------
/lib/kataKotor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: SeroBot Team
3 | * @ Create Time: 2021-05-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-07-09 07:38:36
6 | * @ Description: Search kata kotor dan nsfw
7 | */
8 |
9 | import fs from 'fs-extra'
10 | const { readFileSync } = fs
11 | const kataKasar = JSON.parse(readFileSync('./settings/katakasar.json'))
12 | const nsfwQuery = JSON.parse(readFileSync('./settings/nsfwquery.json'))
13 |
14 | const inArray = (needle, haystack) => {
15 | let length = haystack.length
16 | for (let i = 0; i < length; i++) {
17 | if (haystack[i] == needle) return true
18 | }
19 | return false
20 | }
21 |
22 | const cariKasar = (sentence) => new Promise((resolve) => {
23 | if (sentence !== undefined) {
24 | let words = sentence.split(/\s/g)
25 | for (let word of words) {
26 | if (inArray(word.toLowerCase(), kataKasar)) {
27 | resolve(true)
28 | }
29 | }
30 | resolve(false)
31 | }
32 | })
33 |
34 | const cariNsfw = (sentence) => new Promise((resolve) => {
35 | if (sentence !== undefined) {
36 | let words = sentence.split(/\s/g)
37 | for (let word of words) {
38 | if (inArray(word.toLowerCase(), nsfwQuery)) {
39 | resolve(true)
40 | }
41 | }
42 | resolve(false)
43 | }
44 | })
45 |
46 | export default cariKasar
47 | export { cariNsfw }
--------------------------------------------------------------------------------
/lib/list.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: SeroBot Team
3 | * @ Create Time: 2021-04-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-07-11 00:14:53
6 | * @ Description: List crud bos pake lowdb
7 | */
8 |
9 | import appRoot from 'app-root-path'
10 | import { LowSync, JSONFileSync } from 'lowdb'
11 | import lodash from 'lodash'
12 |
13 | const adapter = new JSONFileSync(appRoot + '/data/list.json')
14 | const db = new LowSync(adapter)
15 | db.read()
16 | db.data || (db.data = { chats: [] })
17 | db.write()
18 | db.chain = lodash.chain(db.data)
19 |
20 | /**
21 | * Create list.
22 | * @param {String} chatId
23 | * @param {String} listName
24 | * @param {String} desc
25 | * @returns {Promise} `Promise` that resolve `true` if success
26 | */
27 | const createList = (chatId, listName, desc) => new Promise((resolve, reject) => {
28 | try {
29 | const find = db.chain.get('chats').find({ id: chatId }).value()
30 | if (find && find.id === chatId) {
31 | const getList = db.chain.get('chats').find({ id: chatId }).value()?.list || []
32 | const isIn = lodash.findIndex(getList, { name: listName })
33 | if (isIn != -1) {
34 | resolve(false)
35 | } else {
36 | getList.push({ name: listName, desc: desc, listData: [] })
37 | db.chain.get('chats').find({ id: chatId }).set('list', getList).value()
38 | db.data = db.chain
39 | db.write()
40 | resolve(true)
41 | }
42 | } else {
43 | db.chain.get('chats').push({ id: chatId, list: [{ name: listName, desc: desc, listData: [] }] }).value()
44 | db.data = db.chain
45 | db.write()
46 | resolve(true)
47 | }
48 | } catch (err) {
49 | reject(err)
50 | }
51 | })
52 |
53 | /**
54 | * Delete list.
55 | * @param {String} chatId
56 | * @param {String} listName
57 | * @returns {Promise} `Promise` that resolve `true` if success
58 | */
59 | const deleteList = (chatId, listName) => new Promise((resolve, reject) => {
60 | try {
61 | const find = db.chain.get('chats').find({ id: chatId }).value()
62 | if (find && find.id === chatId) {
63 | const getList = db.chain.get('chats').find({ id: chatId }).value()?.list || []
64 | const isIn = lodash.findIndex(getList, { name: listName })
65 | if (isIn != -1) {
66 | getList.splice(isIn, 1)
67 | db.chain.get('chats').find({ id: chatId }).set('list', getList).value()
68 | db.data = db.chain
69 | db.write()
70 | resolve(true)
71 | } else {
72 | resolve(false)
73 | }
74 | } else {
75 | resolve(false)
76 | }
77 | } catch (err) {
78 | reject(err)
79 | }
80 | })
81 |
82 | /**
83 | * Get all chat listName.
84 | * @param {String} chatId
85 | * @returns {Promise} Promise that resolve `listName[]`
86 | */
87 | const getListName = (chatId) => new Promise((resolve, reject) => {
88 | try {
89 | const find = db.chain.get('chats').find({ id: chatId }).value()
90 | if (find && find.id === chatId) {
91 | let res = []
92 | const getList = db.chain.get('chats').find({ id: chatId }).value()?.list || []
93 | getList.forEach(_ => {
94 | res.push(_.name)
95 | })
96 | resolve(res)
97 | } else {
98 | resolve(false)
99 | }
100 | } catch (err) {
101 | reject(err)
102 | }
103 | })
104 |
105 | /**
106 | * Manipulate list.
107 | * @param {String} chatId
108 | * @param {String} listName
109 | * @param {Array} newData
110 | * @param {Number} Index required if using `delete` action
111 | * @param {String} action can be `add` or `delete` or `edit`
112 | * @returns {Promise} `Data` object
113 | */
114 | const ListData = (chatId, listName, newData, index, action) => new Promise((resolve, reject) => {
115 | try {
116 | const getList = db.chain.get('chats').find({ id: chatId }).value()?.list || []
117 | const isIn = lodash.findIndex(getList, { name: listName })
118 | if (isIn != -1) {
119 | let data = db.chain.get('chats').filter({ id: chatId }).map(`list[${isIn}]`)
120 | .find({ name: listName }).update('listData', n => {
121 | switch (action) {
122 | case 'add': {
123 | return n.concat(newData)
124 | }
125 | case 'delete': {
126 | let temp = n
127 | temp.splice(index, 1)
128 | return temp
129 | }
130 | case 'edit': {
131 | let temp = n
132 | temp.splice(index, 1, newData)
133 | return temp
134 | }
135 | }
136 | }).value()
137 | db.data = db.chain
138 | db.write()
139 | resolve(data)
140 | } else {
141 | resolve(false)
142 | }
143 | } catch (err) {
144 | reject(err)
145 | }
146 | })
147 |
148 | /**
149 | * Add list content to list data.
150 | * @param {String} chatId
151 | * @param {String} listName
152 | * @param {Array} newData[]
153 | * @returns {Promise} `Promise` that resolve `listData[]` or `false` if not exist
154 | */
155 | const addListData = (chatId, listName, newData) => new Promise((resolve, reject) => {
156 | let res = ListData(chatId, listName, newData, null, 'add').catch(err => {
157 | reject(err)
158 | })
159 | resolve(res)
160 | })
161 |
162 | /**
163 | * get list content of list data.
164 | * @param {String} chatId
165 | * @param {String} listName
166 | * @returns {Promise} `Promise` that resolve `listContentData[]` or `false` if not exist
167 | */
168 | const getListData = (chatId, listName) => new Promise((resolve, reject) => {
169 | let res = ListData(chatId, listName, [], null, 'add').catch(err => {
170 | reject(err)
171 | })
172 | resolve(res)
173 | })
174 |
175 | /**
176 | * remove list content of list data.
177 | * @param {String} chatId
178 | * @param {String} listName
179 | * @param {Number} index
180 | * @returns {Promise} `Promise` that resolve `listContentData[]` or `false` if not exist
181 | */
182 | const removeListData = (chatId, listName, index) => new Promise((resolve, reject) => {
183 | let res = ListData(chatId, listName, null, index, 'delete').catch(err => {
184 | reject(err)
185 | })
186 | resolve(res)
187 | })
188 |
189 | /**
190 | * edit list content of list data.
191 | * @param {String} chatId
192 | * @param {String} listName
193 | * @param {Number} index
194 | * @returns {Promise} `Promise` that resolve `listContentData[]` or `false` if not exist
195 | */
196 | const editListData = (chatId, listName, newData, index) => new Promise((resolve, reject) => {
197 | let res = ListData(chatId, listName, newData, index, 'edit').catch(err => {
198 | reject(err)
199 | })
200 | resolve(res)
201 | })
202 |
203 | // BY SEROBOT => https://github.com/dngda/bot-whatsapp
204 |
205 | export default {
206 | createList,
207 | deleteList,
208 | getListName,
209 | addListData,
210 | getListData,
211 | editListData,
212 | removeListData
213 | }
--------------------------------------------------------------------------------
/lib/location.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: ArugaZ
3 | * @ Create Time: 2021-05-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-06-22 15:05:07
6 | * @ Description:
7 | */
8 |
9 | import { fetchJson } from '../utils/fetcher.js'
10 |
11 | async function getZoneStatus(latitude, longitude, userId = '2d8ecc70-8310-11ea-84f8-13de98afc5a4') {
12 | return new Promise((resolve, reject) => {
13 | const options = {
14 | method: 'POST',
15 | headers: {
16 | Authorization: 'Basic dGVsa29tOmRhMWMyNWQ4LTM3YzgtNDFiMS1hZmUyLTQyZGQ0ODI1YmZlYQ== ',
17 | Accept: 'application/json'
18 | },
19 | body: JSON.stringify({
20 | latitude: latitude.toString(),
21 | longitude: longitude.toString(),
22 | userId
23 | })
24 | }
25 | fetchJson('https://api.pedulilindungi.id/zone/v1', options)
26 | .then(json => {
27 | const result = {
28 | kode: json.data.zone,
29 | status: '',
30 | optional: ''
31 | }
32 |
33 | switch (json.data.zone) {
34 | case 'red':
35 | result.status = 'Anda berada di Zona Merah penyebaran COVID-19.'
36 | result.optional = 'Zona Merah adalah area yang sudah terdapat kasus Positif COVID-19.'
37 | break
38 | case 'yellow':
39 | result.status = 'Anda berada di Zona Kuning penyebaran COVID-19.'
40 | result.optional = 'Zona Kuning adalah area yang sudah terdapat kasus ODP atau PDP COVID-19.'
41 | break
42 | case 'green':
43 | result.status = 'Anda berada di Zona Hijau penyebaran COVID-19.'
44 | result.optional = 'Zona Hijau adalah area yang belum terdapat kasus PDP atau Positif COVID-19.'
45 | break
46 | }
47 |
48 | if (!json.success && json.message == 'Anda berada di zona aman.') {
49 | result.kode = 'green'
50 | result.status = 'Anda berada di Zona Hijau penyebaran COVID-19.'
51 | result.optional = 'Zona Hijau adalah area yang belum terdapat kasus PDP atau Positif COVID-19.'
52 | }
53 | resolve(result)
54 | })
55 | .catch((err) => reject(err))
56 | })
57 | }
58 |
59 | async function getArea(latitude, longitude, size = 10) {
60 | return new Promise((resolve, reject) => {
61 | const options = {
62 | method: 'GET',
63 | headers: {
64 | Authorization: ' Basic dGVsa29tOmRhMWMyNWQ4LTM3YzgtNDFiMS1hZmUyLTQyZGQ0ODI1YmZlYQ== ',
65 | 'Content-Type': ' application/json '
66 | }
67 | }
68 | fetchJson(`https://api.pedulilindungi.id/zone/v1/location/area?latitude=${latitude}&longitude=${longitude}&page=1&size=${size}`, options)
69 | .then(json => {
70 | if (json.success && json.code == 200) resolve(json)
71 | })
72 | .catch((err) => reject(err))
73 | })
74 | }
75 |
76 | const getLocationData = async (latitude, longitude) => {
77 | try {
78 | const responses = await Promise.all([getZoneStatus(latitude, longitude), getArea(latitude, longitude)])
79 | const result = {
80 | kode: 200,
81 | status: responses[0].status,
82 | optional: responses[0].optional,
83 | data: []
84 | }
85 | responses[1].data.map((x) => result.data.push(x))
86 | return result
87 | } catch (err) {
88 | console.log(err)
89 | return { kode: 0 }
90 | }
91 | }
92 |
93 | export default getLocationData
94 |
--------------------------------------------------------------------------------
/lib/menu.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: SeroBot Team
3 | * @ Create Time: 2021-05-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-08-02 17:58:32
6 | * @ Description: Menu
7 | */
8 |
9 | /*
10 |
11 | Dimohon untuk tidak menghapus link github saya, butuh support dari kalian! makasih.
12 |
13 | */
14 |
15 | const textTnC = () => {
16 | return `
17 | SeroBot adalah *Bot* yg merupakan akronim dari kata Robot yang berarti sebuah sistem yang diprogram oleh komputer.
18 | Sehingga respon atau balasan yang dilakukan oleh bot bukanlah dari Manusia.
19 |
20 | Dengan menggunakan bot ini maka anda *setuju* dengan syarat dan kondisi sebagai berikut:
21 | - Berilah jeda dari setiap perintah.
22 | - Dilarang menelfon bot, atau kalian akan kena block otomatis.
23 | - Dilarang keras melakukan spam. Ketahuan = auto banned.
24 | - Bot tidak akan merespon curhatan kalian.
25 | - Bot tidak menyimpan gambar/media yang dikirimkan.
26 | - Bot tidak menyimpan data pribadi anda di server kami.
27 | - Bot tidak bertanggung jawab atas perintah anda kepada bot ini.
28 | - Bot berjalan di server secara terpisah (Bukan dalam HP owner).
29 | - Bot akan secara berkala dimonitoring oleh owner, jadi ada kemungkinan chat akan terbaca oleh owner.
30 | - Bot akan dilakukan pembersihan setiap awal bulan atau saat dirasa diperlukan.
31 |
32 | Get interested in this open source project?
33 | Collaborate now: https://github.com/dngda/bot-whatsapp
34 |
35 | Best regards,
36 |
37 | -Danang.`
38 | }
39 |
40 | /*
41 |
42 | Dimohon untuk tidak menghapus link github saya, butuh support dari kalian! makasih.
43 |
44 | */
45 |
46 | const textMenu = (pushname, t, prefix) => {
47 | let m = (namaMenu) => `*${prefix}${namaMenu}*`
48 | let n = (new Date(t * 1000)).getHours()
49 | let ucapan = ''
50 | if (3 < n && n <= 9) ucapan = `*Selamat pagi 🌤️*`
51 | else if (9 < n && n <= 14) ucapan = `*Selamat siang ☀️*`
52 | else if (14 < n && n <= 18) ucapan = `*Selamat sore 🌻*`
53 | else ucapan = `*Selamat malam 💤*`
54 | return `
55 | Halo, ${pushname}!
56 | ${ucapan} 👋️
57 | Perkenalkan saya
58 | ${q3} ___ ___ _
59 | / __| ___ _ _ ___| _ ) ___| |_
60 | \\__ \\/ -_) '_/ _ \\ _ \\/ _ \\ _|
61 | |___/\\___|_| \\___/___/\\___/\\__|${q3}
62 |
63 | Berikut adalah beberapa fitur yang ada pada bot ini!✨
64 | ${readMore}
65 | Note:
66 | Jangan ditelfon atau blocked instantly! ⛔
67 | Kirim perintah tanpa argumen untuk melihat maksud dari setiap fitur.
68 | Selain ${q3}(/)${q3} bot juga akan merespon simbol berikut:
69 | ${q3}\\ / ! $ ^ % & + . , -${q3}
70 |
71 | Operasi kalkulator gunakan prefix (=)
72 | (cth: =10+2+4)
73 |
74 | ╔══✪〘 ‼️ Wajib ‼️ 〙✪
75 | ╠> ${m('tnc')} atau ${m('rules')}
76 | ╚> Baca dan pahami sebelum melanjutkan
77 |
78 | ╔══✪〘 💬 Informasi 💬 〙✪
79 | ╠> ${m('donate')} atau ${m('donasi')}
80 | ╠> ${m('ping')} atau ${m('speed')}
81 | ╠> ${m('owner')}
82 | ╠> ${m('stat')}
83 | ╚══✪
84 |
85 | ╔══✪〘 ⚙ Converter ⚙ 〙✪
86 | ╠> ${m('getimage')} atau ${m('toimg')}
87 | ║ Mengubah sticker menjadi gambar.
88 | ╠> ${m('sticker')} atau ${m('stiker')} atau ${m('s')}
89 | ║ Mengubah gambar/video menjadi sticker.
90 | ╠> ${m('stickergiphy')}
91 | ║ Mengubah url giphy menjadi sticker.
92 | ╠> ${m('doctopdf')} atau ${m('pdf')}
93 | ║ Mengubah dokumen menjadi pdf.
94 | ╠> ${m('qrcode')} atau ${m('qr')}
95 | ║ Membuat QRcode dari text.
96 | ╠> ${m('tts')} atau ${m('say')}
97 | ║ Mengubah text menjadi suara Google.
98 | ╠> ${m('shortlink')}
99 | ║ Pemendek url menggunakan tinyurl.
100 | ╠> ${m('translate')}
101 | ║ Google translate text.
102 | ╠> ${m('memefy')}
103 | ║ Menambahkan text pada gambar.
104 | ╠> ${m('tomp3')}
105 | ║ Convert video ke audio.
106 | ╠> ${m('hilih')}
107 | ║ Mengubah text vokal menjadi huruf i.
108 | ╠> ${m('ssweb')}
109 | ║ Screenshot url website.
110 | ╠> ${m('take')}
111 | ║ Edit sticker pack dan author watermark
112 | ╠> ${m('flip')}
113 | ║ Balik gambar scr horizontal/vertikal.
114 | ╠> ${m('ocr')}
115 | ║ Scan text dari gambar.
116 | ╚══✪
117 |
118 | ╔══✪〘 🧬 Maker 🧬 〙✪
119 | ╠> ${m('trigger')} atau ${m('trigger2')}
120 | ║ Add trigger effect pd gambar (sticker)
121 | ╠> ${m('wasted')}
122 | ║ Add wasted effect pd gambar (sticker)
123 | ╠> ${m('attp')}
124 | ║ Animated text to picture (sticker)
125 | ╠> ${m('ttp')}
126 | ║ Text to picture (sticker)
127 | ╚══✪
128 |
129 | ╔══✪〘 📩 Downloader 📩 〙✪
130 | ╠> ${m('tiktokmp3')} atau ${m('ttmp3')}
131 | ║ Download musik dari link Tiktok.
132 | ╠> ${m('tiktok')} atau ${m('tt')}
133 | ║ Download Tiktok tanpa watermark.
134 | ╠> ${m('igstory')}
135 | ║ Download Igstory dari username.
136 | ╠> ${m('ytmp3')}
137 | ║ Download mp3 dari link Youtube.
138 | ╠> ${m('ytmp4')}
139 | ║ Download mp4 dari link Youtube.
140 | ╠> ${m('fbdl')}
141 | ║ Download media dari link Facebook.
142 | ╠> ${m('twdl')}
143 | ║ Download media dari link Twitter.
144 | ╠> ${m('igdl')}
145 | ║ Download media dari link Instagram.
146 | ╚══✪
147 |
148 | ╔══✪〘 🔊 Audio Converter 🔊 〙✪
149 | ║ Menambahkan efek suara pada audio.
150 | ╠> ${m('nightcore')}
151 | ╠> ${m('deepslow')}
152 | ╠> ${m('samarkan')}
153 | ╠> ${m('vibrato')}
154 | ╠> ${m('earrape')}
155 | ╠> ${m('reverse')}
156 | ╠> ${m('robot')}
157 | ╠> ${m('8d')}
158 | ╠══✪
159 | ╠> ${m('cf')}
160 | ║ Custom ffmpeg complex filter (Expert user only)
161 | ╚══✪
162 |
163 | ╔══✪〘 🕋 Islam 🕋 〙✪
164 | ╠> ${m('listsurah')}
165 | ║ Daftar surah yang tersedia.
166 | ╠> ${m('infosurah')}
167 | ║ Info surah yang diinginkan.
168 | ╠> ${m('jsholat')}
169 | ║ Jadwal sholat sesuai daerah.
170 | ╠> ${m('alaudio')}
171 | ║ Audio dari surah yg diinginkan.
172 | ╠> ${m('tafsir')}
173 | ║ Tafsir surah yg diinginkan.
174 | ╠> ${m('surah')}
175 | ║ Menampilkan ayat dari surah yang diinginkan.
176 | ╚══✪
177 |
178 | ╔══✪〘 🎊 Random 🎊 〙✪
179 | ║ Random berarti acak.
180 | ╠> ${m('katabijak')}
181 | ╠> ${m('skripsi')}
182 | ╠> ${m('pantun')}
183 | ╠> ${m('fakta')}
184 | ╠> ${m('quote')}
185 | ╠> ${m('anime')}
186 | ╠> ${m('memes')}
187 | ╚══✪
188 |
189 | ╔══✪〘 🔎 Search 🔍 〙✪
190 | ╠> ${m('pinterest')} atau ${m('pin')}
191 | ║ Search gambar dari pinterest.
192 | ╠> ${m('gimages')} atau ${m('gimg')}
193 | ║ Search gambar dari Google.
194 | ╠> ${m('gsearch')} atau ${m('gs')}
195 | ║ Screenshot search dari Google.
196 | ╠> ${m('artinama')}
197 | ║ Primbon arti nama, hanya hiburan.
198 | ╠> ${m('sreddit')}
199 | ║ Search gambar dari Subreddit.
200 | ╠> ${m('lirik')}
201 | ║ Search lirik lagu.
202 | ╠> ${m('play')}
203 | ║ Search lagu dari Youtube.
204 | ╠> ${m('kbbi')}
205 | ║ Search arti kata dalam KBBI.
206 | ╠> ${m('yt')}
207 | ║ Search Youtube.
208 | ╚══✪
209 |
210 | ╔══✪〘 🎉 Hiburan 🎉 〙✪
211 | ╠> ${m('tebakgambar')} atau ${m('tbg')}
212 | ║ Main tebak gambar.
213 | ╠> ${m('tebakjenaka')} atau ${m('tbj')}
214 | ║ Main tebak jenaka.
215 | ╠> ${m('tebaklirik')} atau ${m('tbl')}
216 | ║ Main tebak lirik.
217 | ╠> ${m('tebakkata')} atau ${m('tbk')}
218 | ║ Main tebak kata.
219 | ╠> ${m('apakah')}
220 | ║ Puja kerang ajaib!!!
221 | ╠> ${m('sfx')}
222 | ║ Mengirimkan audio yg tersedia.
223 | ╠> ${m('ToD')}
224 | ║ Group only. Truth atau dare?
225 | ╚══✪
226 |
227 | ╔══✪〘 ℹ Info ℹ 〙✪
228 | ╠> ${m('cekcovid')}
229 | ║ Cek sebaran covid sesuai lokasi.
230 | ╠> ${m('crjogja')}
231 | ║ Radar cuaca lokasi Jogja.
232 | ╠> ${m('buildgi')}
233 | ║ Build GI sesuai nama character.
234 | ╠> ${m('cuaca')}
235 | ║ Informasi cuaca sesuai daerah.
236 | ╠> ${m('resi')}
237 | ║ Cek resi barang sesuai kurir.
238 | ╚══✪
239 |
240 | ╔══✪〘 🤬 Anti Toxic 🤬 〙✪
241 | ║ Group only. Anti kata kasar.
242 | ╠> ${m('antikasar')}
243 | ╠> ${m('klasemen')}
244 | ╠> ${m('reset')}
245 | ╚══✪
246 |
247 | ╔══✪〘 🤩 More Useful 🤩 〙✪
248 | ╠> ${m('tagall')} atau ${m('alle')}
249 | ║ Group only. Tag seluruh member.
250 | ╠> ${m('join')} atau ${m('sewa')}
251 | ║ Sewa bot untuk join group kalau slot tersedia.
252 | ╠> ${m('listonline')}
253 | ║ Group only. Tag seluruh member yang online.
254 | ╠> ${m('remind')}
255 | ║ Kirimkan pesan ulang sesuai waktu yg ditentukan.
256 | ╠> ${m('list')}
257 | ║ Membuat list atau daftar yg disimpan di bot.
258 | ╠> ${m('note')}
259 | ║ Membuat note atau catatan yg disimpan di bot.
260 | ╠> ${m('bye')}
261 | ║ Group only. Keluarkan bot.
262 | ╠> ${m('del')}
263 | ║ Hapus pesan bot.
264 | ║
265 | ╚══✪〘 *SeroBot* 〙✪
266 |
267 | Note :
268 | Reply pesanmu yang berisi perintah
269 | dengan '..' (titik double) untuk mengirimkannya kembali.
270 |
271 | Chat dengan trigger (bot, sero, serobot) atau tag akan dijawab oleh simsimi.
272 |
273 | Hope you have a great day!✨
274 | Kalau anda merasa bot ini membantu/berguna silakan *berdonasi* ✨`
275 | }
276 |
277 | /*
278 |
279 | Dimohon untuk tidak menghapus link github saya, butuh support dari kalian! makasih.
280 |
281 | */
282 |
283 | const textAdmin = (prefix) => {
284 | let m = (namaMenu) => `*${prefix}${namaMenu}*`
285 | return `
286 | ⚠ [ *Admin Group Only* ] ⚠
287 | Berikut adalah fitur admin grup yang ada pada bot ini!
288 |
289 | ╔══✪〘 Admin Only 〙✪
290 | ╠> ${m('groupstats')}
291 | ║ Cek status pengaturan group
292 | ╠> ${m('mutegroup')} atau ${m('group')} buka/tutup
293 | ║ Selain admin gabisa kirim pesan
294 | ╠> ${m('enablebot')} atau ${m('disablebot')}
295 | ║ Hidupkan atau matikan bot untuk group.
296 | ╠> ${m('antilinkgroup')} on/off
297 | ║ Kick otomatis yg kirim link group
298 | ╠> ${m('antikasarkick')} on/off
299 | ║ Kick otomatis yg toksik di group
300 | ╠> ${m('antilink')} on/off
301 | ║ Kick otomatis yg kirim semua jenis link
302 | ╠> ${m('antivirtex')} on/off
303 | ║ Kick otomatis yg kirim pesan terlalu panjang
304 | ╠> ${m('antidelete')} on/off
305 | ║ Anti delete pesan di group
306 | ╠> ${m('welcome')} on/off
307 | ║ Menyambut member baru join
308 | ╠> ${m('setprofile')}
309 | ║ Ganti foto group
310 | ╠> ${m('setname')}
311 | ║ Ganti nama group
312 | ╠> ${m('grouplink')}
313 | ║ Untuk mendapatkan group link
314 | ╠> ${m('promote')}
315 | ║ Jadiin admin
316 | ╠> ${m('demote')}
317 | ║ Cabut hak admin
318 | ╠> ${m('revoke')}
319 | ║ Reset group link
320 | ╠> ${m('kick')}
321 | ║ Kick member
322 | ╠> ${m('add')}
323 | ║ Tambah member
324 | ║
325 | ║ (fitur welcome sering error, mending gak usah)
326 | ║
327 | ╚═〘 *SeroBot* 〙
328 | `
329 | }
330 |
331 | /*
332 |
333 | Dimohon untuk tidak menghapus link github saya, butuh support dari kalian! makasih.
334 |
335 | */
336 |
337 | const textOwner = (prefix) => {
338 | let m = (namaMenu) => `*${prefix}${namaMenu}*`
339 | return `
340 | ⚠ [ *Owner Only* ] ⚠
341 | Berikut adalah fitur owner yang ada pada bot ini!
342 |
343 | ╔══✪〘 Owner Only 〙✪
344 | ╠> ${m('addkasar')}
345 | ║ Add kata kasar ke database. Restart required.
346 | ╠> ${m('restart')}
347 | ║ Restart nodejs. Windows only.
348 | ╠> ${m('listgroup')}
349 | ║ Return all group list
350 | ╠> ${m('listsewa')}
351 | ║ Return all group list
352 | ╠> ${m('ban')}
353 | ║ Ban user.
354 | ╠> ${m('unban')}
355 | ║ Unban user.
356 | ╠> ${m('bc')}
357 | ║ Broadcast all chats.
358 | ╠> ${m('bcgroup')}
359 | ║ Broadcast all group.
360 | ╠> ${m('leaveall')}
361 | ║ Leave all group kecuali premium (Pembersihan)
362 | ╠> ${m('clearexitedgroup')}
363 | ║ Delete chat group yang sudah keluar.
364 | ╠> ${m('deleteall')}
365 | ║ Delete semua chat termasuk group tanpa keluar group.
366 | ╠> ${m('clearall')}
367 | ║ Clear semua chat tanpa menghapus chats.
368 | ╠> ${m('cleanchat')}
369 | ║ Simulate clean all chat seperti saat 01:01
370 | ╠> ${m('unblock')} atau ${m('u')}
371 | ║ Unblock user.
372 | ╠> ${m('getinfo')}
373 | ║ Get info dari link group.
374 | ╠> ${m('getstory')}
375 | ║ Get story wa.
376 | ╠> ${m('addprem')}
377 | ║ Add group ke premium.
378 | ╠> _>_
379 | ║ Eval.
380 | ╠> _$_
381 | ║ Shell.
382 | ║
383 | ╚═〘 *SeroBot* 〙
384 | `
385 | }
386 |
387 | /*
388 |
389 | Dimohon untuk tidak menghapus link github saya, butuh support dari kalian! makasih.
390 |
391 | */
392 |
393 | const textDonasi = () => {
394 | return `
395 | Hai, terimakasih telah menggunakan bot ini, untuk mendukung bot ini kamu dapat membantu dengan berdonasi dengan cara:
396 |
397 | Ovo/Gopay/Dana: 0851 6146 7958
398 | Pulsa: 0858 7750 2176
399 | Paypal: https://paypal.me/dngda
400 | Saweria: https://saweria.co/dngda
401 | Trakteer: https://trakteer.id/dngda
402 |
403 | Bitcoin : 14vHto4CCXmEwC6BVsifyVmMxxsGydRHCS
404 | USDT (Trc20) : TB29LW37akLR5VmCkatK3ppxftUogSA8SU
405 |
406 | Berapapun nominalnya akan sangat membantu pengembangan bot ini.
407 | Terimakasih. ~Danang`
408 | }
409 |
410 | export default {
411 | textTnC,
412 | textMenu,
413 | textOwner,
414 | textAdmin,
415 | textDonasi
416 | }
--------------------------------------------------------------------------------
/lib/note.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: SeroBot Team
3 | * @ Create Time: 2021-06-13 17:24:58
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-07-11 00:16:06
6 | * @ Description: Note crud bos pake lowdb
7 | */
8 |
9 | import appRoot from 'app-root-path'
10 | import { LowSync, JSONFileSync } from 'lowdb'
11 | import lodash from 'lodash'
12 |
13 | const adapter = new JSONFileSync(appRoot + '/data/notes.json')
14 | const db = new LowSync(adapter)
15 | db.read()
16 | db.data || (db.data = { chats: [] })
17 | db.write()
18 | db.chain = lodash.chain(db.data)
19 |
20 | /**
21 | * Create note.
22 | * @param {String} chatId
23 | * @param {String} noteName
24 | * @param {String} content
25 | * @returns {Promise} `Promise` that resolve `true` if success
26 | */
27 | const createNote = (chatId, noteName, content) => new Promise((resolve, reject) => {
28 | try {
29 | db.read()
30 | const find = db.chain.get('chats').find({ id: chatId }).value()
31 | if (find && find.id === chatId) {
32 | const getNote = db.chain.get('chats').find({ id: chatId }).value()?.note || []
33 | const isIn = lodash.findIndex(getNote, { name: noteName })
34 | if (isIn != -1) {
35 | resolve(false)
36 | } else {
37 | getNote.push({ name: noteName, content: content })
38 | db.chain.get('chats').find({ id: chatId }).set('note', getNote).value()
39 | db.data = db.chain
40 | db.write()
41 | resolve(true)
42 | }
43 | } else {
44 | db.chain.get('chats').push({ id: chatId, note: [{ name: noteName, content: content }] }).value()
45 | db.data = db.chain
46 | db.write()
47 | resolve(true)
48 | }
49 | } catch (err) {
50 | reject(err)
51 | }
52 | })
53 |
54 | /**
55 | * Delete note.
56 | * @param {String} chatId
57 | * @param {String} noteName
58 | * @returns {Promise} `Promise` that resolve `true` if success
59 | */
60 | const deleteNote = (chatId, noteName) => new Promise((resolve, reject) => {
61 | try {
62 | db.read()
63 | const find = db.chain.get('chats').find({ id: chatId }).value()
64 | if (find && find.id === chatId) {
65 | const getNote = db.chain.get('chats').find({ id: chatId }).value()?.note || []
66 | const isIn = lodash.findIndex(getNote, { name: noteName })
67 | if (isIn != -1) {
68 | getNote.splice(isIn, 1)
69 | db.chain.get('chats').find({ id: chatId }).set('note', getNote).value()
70 | db.data = db.chain
71 | db.write()
72 | resolve(true)
73 | } else {
74 | resolve(false)
75 | }
76 | } else {
77 | resolve(false)
78 | }
79 | } catch (err) {
80 | reject(err)
81 | }
82 | })
83 |
84 | /**
85 | * Get all chats noteName.
86 | * @param {String} chatId
87 | * @returns {Promise} Promise that resolve `noteName[]`
88 | */
89 | const getNoteName = (chatId) => new Promise((resolve, reject) => {
90 | try {
91 | db.read()
92 | const find = db.chain.get('chats').find({ id: chatId }).value()
93 | if (find && find.id === chatId) {
94 | let res = []
95 | const getNote = db.chain.get('chats').find({ id: chatId }).value()?.note || []
96 | getNote.forEach(_ => {
97 | res.push(_.name)
98 | })
99 | resolve(res)
100 | } else {
101 | resolve(false)
102 | }
103 | } catch (err) {
104 | reject(err)
105 | }
106 | })
107 |
108 | /**
109 | * Get note content.
110 | * @param {String} chatId
111 | * @param {String} noteName
112 | * @returns {Promise} `Data` object
113 | */
114 | const getNoteData = (chatId, noteName) => new Promise((resolve, reject) => {
115 | try {
116 | db.read()
117 | const getNote = db.chain.get('chats').find({ id: chatId }).value()?.note || []
118 | const isIn = lodash.findIndex(getNote, { name: noteName })
119 | if (isIn != -1) {
120 | let data = db.chain.get('chats').filter({ id: chatId }).map(`note[${isIn}]`)
121 | .find({ name: noteName }).value()
122 | resolve(data)
123 | } else {
124 | resolve(false)
125 | }
126 | } catch (err) {
127 | reject(err)
128 | }
129 | })
130 | // BY SEROBOT => https://github.com/dngda/bot-whatsapp
131 |
132 | export default {
133 | createNote,
134 | deleteNote,
135 | getNoteName,
136 | getNoteData,
137 | }
--------------------------------------------------------------------------------
/lib/resep.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: ArugaZ
3 | * @ Create Time: 2021-05-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-06-28 19:51:47
6 | * @ Description:
7 | */
8 |
9 | import axios from 'axios'
10 | import Crypto from 'crypto'
11 | const { get } = axios
12 |
13 | const resep = async (menu) => new Promise((resolve, reject) => {
14 | get('https://masak-apa.tomorisakura.vercel.app/api/search/?q=' + menu)
15 | .then(async (res) => {
16 | const { results } = await res.data
17 | const random = Crypto.randomInt(0, 16)
18 | get('https://masak-apa.tomorisakura.vercel.app/api/recipe/' + results[random].key)
19 | .then(async (result) => {
20 | const { results: resData } = await result.data
21 | const bahannya = `${resData.ingredient}`
22 | const bahan = bahannya.replace(/,/g, '\n')
23 | const tutornya = `${resData.step}`
24 | const tutornih = tutornya.replace(/,/g, '\n')
25 | const tutor = tutornih.replace(/.,/g, '\n')
26 | const hasil = `*Judul:* ${resData.title}\n*Penulis:* ${resData.author.user}\n*Rilis:* ${resData.author.datePublished}\n*Level:* ${resData.dificulty}\n*Waktu:* ${resData.times}\n*Porsi:* ${resData.servings}\n\n*Bahan-bahan:*\n${bahan}\n\n*Step-by-step:*\n${tutor}`
27 | resolve(hasil)
28 | })
29 | })
30 | .catch((err) => {
31 | console.log(err)
32 | reject(err)
33 | })
34 | })
35 |
36 | export default resep
37 |
--------------------------------------------------------------------------------
/lib/schedule.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: SeroBot Team
3 | * @ Create Time: 2021-05-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-06-25 13:48:13
6 | * @ Description: Cron not cron job message wkwkw
7 | */
8 |
9 | import { scheduleJob } from 'node-schedule'
10 | import appRoot from 'app-root-path'
11 | import { LowSync, JSONFileSync } from 'lowdb'
12 | import lodash from 'lodash'
13 |
14 | // Use JSON file for storage
15 | const adapter = new JSONFileSync(appRoot + '/data/schedule.json')
16 | const db = new LowSync(adapter)
17 | db.read()
18 | db.data || (db.data = { jobs: [] })
19 | db.write()
20 | db.chain = lodash.chain(db.data)
21 |
22 | const futureMilis = (client, msg, content, milis, isQuoted) => new Promise((resolve, reject) => {
23 | const when = new Date(Date.now() + milis)
24 | if (when == null || when == 'null') reject(`futureMilis returned` + false)
25 | scheduleJob(when, async function (txt) {
26 | await sendMsg(client, isQuoted, msg.from, txt, isQuoted ? msg.quotedMsgObj.id : null).catch(e => reject(e))
27 | delJob(msg.from, when)
28 |
29 | }.bind(null, content))
30 | const quotedId = isQuoted ? msg.quotedMsgObj.id : null
31 | saveJob(msg.from, quotedId, content, when, isQuoted)
32 | resolve(true)
33 | })
34 |
35 | const loadJob = (client, from, quotedId, content, date, isQuoted) => new Promise((resolve, reject) => {
36 | var now = new Date()
37 | var dateJob = new Date(date)
38 | if (dateJob === null) reject(`loadJob returned` + false)
39 | if (dateJob <= now || dateJob === null) {
40 | delJob(from, date)
41 | resolve(true)
42 | }
43 | scheduleJob(dateJob, async function (txt) {
44 | await sendMsg(client, isQuoted, from, txt, quotedId).catch(e => reject(e))
45 | delJob(from, date)
46 |
47 | }.bind(null, content))
48 | resolve(true)
49 | })
50 |
51 | const sendMsg = (client, isQuoted, from, txt, quotedId) => new Promise((resolve, reject) => {
52 | var content = txt.replace(/@\d+/g, '')
53 | if (!isQuoted) {
54 | client.sendText(from, content).catch(e => reject(e))
55 | } else {
56 | client.reply(from, content, quotedId).catch(e => reject(e))
57 | }
58 | const mentions = txt.trim().match(/@\d+/g) ?? 0
59 | if (mentions !== 0) {
60 | let res = 'Mentions: '
61 | mentions.forEach(m => {
62 | res += `${m} `
63 | })
64 | client.sendTextWithMentions(from, res).catch(e => reject(e))
65 | }
66 | console.log(color('[LOGS]', 'grey'), `ScheduledJob from ${from} Launched`)
67 | resolve(true)
68 | })
69 |
70 | const delJob = (from, date) => new Promise((resolve, reject) => {
71 | try {
72 | const res = db.chain.get('jobs').remove({ from: from, date: date }).value()
73 | db.write()
74 | resolve(res)
75 | } catch (e) {
76 | reject(e)
77 | }
78 | })
79 |
80 | const saveJob = (from, quotedId, content, date, isQuoted) => new Promise((resolve, reject) => {
81 | try {
82 | const res = db.chain.get('jobs').push({
83 | from: from,
84 | quotedId: quotedId,
85 | content: content,
86 | date: date,
87 | isQuoted: isQuoted
88 | }).value()
89 | db.write()
90 | resolve(res)
91 | } catch (e) {
92 | reject(e)
93 | }
94 | })
95 |
96 | export default {
97 | futureMilis,
98 | loadJob
99 | }
--------------------------------------------------------------------------------
/lib/scraper.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-async-promise-executor */
2 | /**
3 | * @ Author: SeroBot Team
4 | * @ Create Time: 2021-05-01 19:29:50
5 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
6 | * @ Modified time: 2021-08-01 20:54:11
7 | * @ Description: Scrape tipis-tipis lah daripada pake api
8 | */
9 |
10 | import lodash from "lodash"
11 | const { sample } = lodash
12 |
13 | import axios from "axios"
14 | import cheerio from "cheerio"
15 |
16 | // BY SEROBOT => https://github.com/dngda/bot-whatsapp
17 |
18 |
19 | /**
20 | * Search KBBI
21 | *
22 | * @param {String} query
23 | * @returns {Promise} arti
24 | */
25 | const kbbi = async (query) => new Promise((resolve, reject) => {
26 | const url = 'https://kbbi.web.id/'
27 |
28 | axios.get(url + query).then(res => {
29 | const $ = cheerio.load(res.data)
30 | const arti = $('div#d1').text().trim()
31 | resolve(arti)
32 | }).catch(reject)
33 | })
34 |
35 | /**
36 | * Search Pinterest using puppeteer
37 | *
38 | * @param {Object} puppeteer browser
39 | * @param {String} query
40 | * @returns {Promise} `Promise` resolve url
41 | */
42 | const pinterest = (browser, query) => new Promise(async (resolve, reject) => {
43 | const url = "https://id.pinterest.com/search/pins/?rs=typed&q="
44 | let page = await browser.newPage()
45 | await page.goto(url + encodeURIComponent(query)).catch((e) => reject(e))
46 | await page.waitForSelector(".Collection", {
47 | visible: true,
48 | })
49 | let resu = await page.$$eval(`img.GrowthUnauthPinImage__Image`, (e) => {
50 | return e.map(el => {
51 | return el.getAttribute("src").replace("236x", "originals")
52 | })
53 | })
54 | resolve(resu)
55 | await page.close()
56 | })
57 | // By RA awokoawk
58 | const pinterestLight = (querry) => new Promise((resolve, reject) => {
59 | let ress = {}
60 | axios.get(`https://id.pinterest.com/search/pins/?q=` + querry, {
61 | headers: {
62 | "sec-ch-ua": "\"Chromium\";v=\"90\", \"Opera GX\";v=\"76\", \";Not A Brand\";v=\"99\"",
63 | "sec-ch-ua-mobile": "?0",
64 | "upgrade-insecure-requests": "1",
65 | "cookie": "csrftoken=ebe0be3a93cea6072be18633add953a2; _b=\"AVezvd6F4UtE24FUsA6INxipyZZDoSpyCc5vaJK4QDYXmExosVEc4h6WkiKhlVtQ430=\"; cm_sub=denied; fba=True; _ga=GA1.2.862909259.1620474446; g_state={\"i_l\":0}; _auth=1; _pinterest_sess=TWc9PSZ0VEZqZmdDSlJYaGU5REIvNklIcVlnMjE5b0ZraTE5REJVQ0JiMUwxTkZZaGFoVk1sRDVhOFlwQzhkQnQ0YkMwRlNyV0lIWUFlK0ZVTkVxYUhKNmlvZ0R1UXlQYTBRRVVhMU1yYkpmcXpHK3UyNjNhckRqUFFOYVJVa3RnVmJtVzd2MmRGaHFMZUpLNVhtaHptTDhWSnBSdXhZY0FhRnRTN3J1S0V4cGtsVTBxeE54NkF2blVNSFV3R0NTQTR1bVVNRURGVGdnYlN5UjdBbk9YcHVGbGI3a1kwd1dEZDgrZVM1SDc3V0pJMm00OWxKUDVNQjBLVlFocTB4Mjg1M1RnbGxBaFAxbS9MTnVzei91cEQvcjBtakp6N0ZnU2t1Y3NxWW1DRDV1Q3h0ankvQ3FEWGh3MXczcXBHNXJpYVNCMHB6dUoxMGF6ZzVxN2VqQVBoSElSd0tiQk41ZVRPQXlOaGNpNzVQMWJSeVZJbCtYYVMxQ1ZRUFUwalU3eGVzMGRySlNzdWo1NG5uaXNFM3ZpT0o0TkZHR1daUXlwaXFQclMwa04raW9xVnVaTTRSVGEzTE03TVlZcmZYVDd5UmVPd2lZaGw4aE9VMHJBd0tidEsrcHdPWk96RlFMekVLTzY3VU1PL0tIYUdwUE1IWVdJNnJXalBkU09Sb3dEaHlQVVR1T1RqNW5Sc2FRdmVkZmhkMk9HNHBCL0ZpZ3NMdmZvVW9ReVltTFBCTlNLWHpray9LNWJ2UTNvTlBzVm9aZjRvYWRvRFhla0dBNzdveWJVYXZmVFp2cnFFNU5DYUVwSHhxeDlIajNIVTlHaEVYdGptWm5mSGVSRmtIMmQwVVVVZlVCVEh6UHB3TnBtdWV0b2l6L3VTc3pXMXFGN3lHS3ZJM3BwL0NrWVJDMm1HY2tROGxuQVFRNS9OUW45R3dtSk8zeFJidVFSTG1qTG5PelAvKzd3T3lrN1NoKzBHVGNTY1pGSEY0bW8xcGVmc3NtclBhTWE2QUMxOXNpQWUwRmo4UHl0ZGpwUzhUQXVhbjYwT0ZJeHhHai8yOWFUVTA1Wkx2czN4VSttLzMvbkFVQ2svWnZvNC9xZ3E4VkhYSFZ5elo4TzhtU0o5c3ZDcEJyYjE3QVI1WHlmTTFhWThvWHQ1T0tSTWRsWnI3a1lpU245dEVLd1lZSXRremtkTUZmcVA2YUg0c1UrSk1JOWJVRzZpcWd3T0NVaFZkdUh3UUdURi9sbDBqT2pBZVV2ZnlTQzc5ZnBMYkFMQ1ZsWjdIYWcmaDc1Uk5kK2I4MjFMUXBaVUthci9rVHpCUWRvPQ==; _pinterest_cm=\"TWc9PSYxZnpkMS9XN29Rd2R0TnpBN0RzVktja1J4NUtINUJqRzNGODFXS0xES1pndWlNVm52a0d3V0JocmVIS3p5eDdnNXNZa0hGelNQNDBSTFRId3ZhTFFIQjRGOW1lNlJZMzFiVlg1MHhSOFpmMGhRZUoySUpJZDIyWlVYMjRXNHRaL1lodFl4eW1jWjNyTklpbytYbHZyd29nRm5DY0pQOGgyUWpDdk9zQ1craXR5VEZoNHV4ZzRnOXV4SUFFSStYZCsmT08zMFI1bktXa3pwSDFtK3NNRWpxWWNpQzNzPQ==\"; _routing_id=\"595f24cd-7f4c-4495-aa67-37212d099cd8\"; sessionFunnelEventLogged=1"
66 | }
67 | }).then(res => {
68 | const $ = cheerio.load(res.data)
69 | let hasil = []
70 | $('body > div > div > div > div > div > div > div > div > div > div > div').each(function (a, b) {
71 | $(b).find('div').each(function (c, d) {
72 | let Link = $(d).find('div > div > div > div > a').find('img').attr('src')
73 | hasil.push(Link)
74 | })
75 | })
76 | let Data = new Set()
77 | hasil.forEach(h => {
78 | if (h === undefined) return
79 | Data.add(h.replace('236x', 'originals'))
80 | })
81 | ress = {
82 | status: res.status,
83 | author: "RA",
84 | result: Array.from(Data)
85 | }
86 | resolve(ress.result)
87 | }).catch(reject)
88 | })
89 |
90 | /**
91 | * Search Google image
92 | *
93 | * @param {Object} puppeteer browser
94 | * @param {String} query
95 | * @returns {Promise} `Promise` that resolve url of image
96 | */
97 | const gimage = (browser, query) => new Promise(async (resolve, reject) => {
98 | const url = "https://www.google.com/search?tbm=isch&q="
99 | let page = await browser.newPage()
100 | await page.goto(url + encodeURIComponent(query)).catch((e) => reject(e))
101 | await page
102 | .content()
103 | .then((html) => {
104 | let pattrn =
105 | /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*(jpg|jpeg))/g
106 | let res = html.match(pattrn)
107 | resolve(sample(res))
108 | })
109 | .catch((e) => reject(e))
110 | await page.close()
111 | })
112 |
113 | /**
114 | * Screenshot web
115 | *
116 | * @param {Object} puppeteer browser
117 | * @param {String} url
118 | * @returns {Promise} `Promise` that resolve `true`
119 | */
120 | const ssweb = (
121 | browser,
122 | path,
123 | url,
124 | viewPort = {
125 | width: 1366,
126 | height: 1080,
127 | }
128 | ) => new Promise(async (resolve, reject) => {
129 | const page = await browser.newPage()
130 | await page.setViewport(viewPort)
131 | await page.goto(url)
132 | setTimeout(async () => {
133 | await page
134 | .screenshot({
135 | path: path,
136 | })
137 | .catch((e) => reject(e))
138 | await page.close()
139 | resolve(true)
140 | }, 5000)
141 | })
142 |
143 | /**
144 | * Ssstik scraper
145 | *
146 | * @param {Object} puppeteer browser
147 | * @param {String} url
148 | * @returns {Promise} `Promise` that resolve obj
149 | */
150 | const ssstik = (browser, url) => new Promise(async (resolve, reject) => {
151 | try {
152 | const page = await browser.newPage()
153 | let baseUrl = "https://ssstik.io"
154 |
155 | await page.goto(baseUrl)
156 | await page.type("#main_page_text", `${url}`)
157 | await page.click("#submit", {
158 | delay: 300,
159 | })
160 |
161 | await page.waitForSelector("#target > div > div.result_overlay", {
162 | delay: 300,
163 | })
164 | let mp4 = await page.$eval(
165 | "#target > div > div.result_overlay > a.without_watermark",
166 | (element) => {
167 | return element.getAttribute("href")
168 | }
169 | )
170 | let mp3 = await page.$eval(
171 | "#target > div > div.result_overlay > a.music",
172 | (element) => {
173 | return element.getAttribute("href")
174 | }
175 | )
176 |
177 | resolve({
178 | mp4: baseUrl + mp4,
179 | mp3: mp3,
180 | })
181 | page.close()
182 | } catch (err) {
183 | if (err.name == 'TimeoutError') resolve(null)
184 | else reject(err)
185 | }
186 | })
187 |
188 | /**
189 | * Snaptik scraper
190 | *
191 | * @param {Object} puppeteer browser instance
192 | * @param {String} url
193 | * @returns {Promise} `Promise` that resolve obj
194 | */
195 | const snaptik = (browser, url) => new Promise(async (resolve, reject) => {
196 | try {
197 | const page = await browser.newPage()
198 | const baseUrl = 'https://snaptik.app/'
199 | await page.goto(baseUrl)
200 | await page.type("#url", `${url}`)
201 | await page.click("#submiturl", {
202 | delay: 300,
203 | })
204 |
205 | await page.waitForSelector("div.snaptik-right", {
206 | delay: 300,
207 | })
208 | let d1 = await page.$eval(
209 | "div.snaptik-right > div > a",
210 | (element) => {
211 | return element.getAttribute("href")
212 | })
213 | let d2 = await page.$eval(
214 | "div.snaptik-right > div > a:nth-child(2)",
215 | (element) => {
216 | return element.getAttribute("href")
217 | }
218 | )
219 | let d3 = await page.$eval(
220 | "div.snaptik-right > div > a:nth-child(3)",
221 | (element) => {
222 | return element.getAttribute("href")
223 | }
224 | )
225 | if (d1 == undefined || d3 == undefined) reject(undefined)
226 | page.close()
227 | resolve({
228 | server1: d1.startsWith('/') ? baseUrl + d1 : d1,
229 | server2: d2.startsWith('/') ? baseUrl + d2 : d2,
230 | source: d3.startsWith('/') ? baseUrl + d3 : d3,
231 | })
232 | } catch (err) {
233 | if (err.name == 'TimeoutError') resolve(null)
234 | else reject(err)
235 | }
236 | })
237 |
238 | /**
239 | * saveFrom scraper
240 | *
241 | * @param {Object} puppeteer browser instance
242 | * @param {String} url
243 | * @returns {Promise} `Promise` that resolve obj
244 | */
245 | const saveFrom = (browser, url, isIG = false) => new Promise(async (resolve, reject) => {
246 | try {
247 | const page = await browser.newPage()
248 | await page.goto("https://en.savefrom.net/20/")
249 | await page.waitForSelector("#sf_url", {
250 | delay: 300,
251 | })
252 | await page.type("#sf_url", `${url}`)
253 | await page.click("#sf_submit", {
254 | delay: 300,
255 | })
256 |
257 | await page.waitForSelector("div.media-result", {
258 | delay: 300,
259 | })
260 |
261 | if (isIG) {
262 | let res = await page.$eval(
263 | `#sf_result > div > div > div.info-box > div.link-box > div.def-btn-box > a`,
264 | (a) => {
265 | return a.getAttribute('href')
266 | }
267 | )
268 | page.close()
269 | resolve(res)
270 | } else {
271 | let res = await page.$$eval(
272 | "#sf_result > div > div.result-box.video > div.info-box > div.link-box > div.drop-down-box > div.list > div > div > div > a",
273 | (a) => {
274 | let resu = a.map(el => {
275 | let data = {}
276 | data.url = el.getAttribute("href")
277 | data.quality = el.getAttribute("data-quality")
278 | data.type = el.getAttribute("data-type")
279 | return data
280 | })
281 | return resu
282 | })
283 | page.close()
284 | resolve(res)
285 | }
286 | } catch (e) {
287 | if (e.name == 'TimeoutError') resolve(null)
288 | else reject(e)
289 | }
290 | })
291 |
292 | /**
293 | * saveFrom scraper
294 | *
295 | * @param {Object} puppeteer browser instance
296 | * @param {String} url
297 | * @returns {Promise} `Promise` that resolve obj
298 | */
299 | const saveFromStory = (browser, username) => new Promise(async (resolve, reject) => {
300 | try {
301 | const page = await browser.newPage()
302 | await page.goto("https://en.savefrom.net/20-download-instagram-stories.html")
303 | await page.waitForSelector("#sf_url", {
304 | delay: 300,
305 | })
306 | await page.type("#sf_url", `${username}`)
307 | await page.click("#sf_submit", {
308 | delay: 300,
309 | })
310 |
311 | await page.waitForSelector("#ig-stories-root > div > div > div.ig-stories__content > ul", {
312 | delay: 300,
313 | })
314 |
315 | let res = await page.$$eval(
316 | "#ig-stories-root > div > div > div.ig-stories__content > ul > li",
317 | (li) => {
318 | let resu = li.map(el => {
319 | return el.querySelector('a').href
320 | })
321 | return resu
322 | })
323 | page.close()
324 | resolve(res)
325 | } catch (e) {
326 | if (e.name == 'TimeoutError') resolve(null)
327 | else reject(e)
328 | }
329 | })
330 |
331 | export default {
332 | pinterestLight,
333 | saveFromStory,
334 | pinterest,
335 | saveFrom,
336 | snaptik,
337 | gimage,
338 | ssstik,
339 | ssweb,
340 | kbbi
341 | }
342 |
--------------------------------------------------------------------------------
/lib/sewa.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: SeroBot Team
3 | * @ Create Time: 2021-06-11 23:08:15
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-07-21 13:03:31
6 | * @ Description: Sewa-sewa crud sih
7 | */
8 |
9 | import fs from 'fs'
10 | import appRoot from 'app-root-path'
11 | import { LowSync, JSONFileSync } from 'lowdb'
12 | import lodash from 'lodash'
13 | const { readFileSync } = fs
14 | const { ownerNumber, prefix } = JSON.parse(readFileSync(appRoot + '/settings/setting.json'))
15 | const adapter = new JSONFileSync(appRoot + '/data/sewa.json')
16 | const db = new LowSync(adapter)
17 | db.read()
18 | db.data || (db.data = { groups: [] })
19 | db.write()
20 | db.chain = lodash.chain(db.data)
21 |
22 | // eslint-disable-next-line no-async-promise-executor
23 | const listenSaweria = (client, browser) => new Promise(async (resolve, reject) => {
24 | try {
25 | let url = JSON.parse(readFileSync(appRoot + '/settings/api.json')).saweriaOverlay
26 |
27 | const page = await browser.newPage()
28 | await page.goto(url)
29 |
30 | await page.exposeFunction('puppeteerLogMutation', async () => {
31 | let who = await page.$eval('div.css-0 > p', (e) => {
32 | return e.textContent
33 | })
34 | let much = await page.$eval('div.css-0 > p:nth-child(2)', (e) => {
35 | return e.textContent
36 | })
37 | let msg = await page.$eval('div.css-0 > p:nth-child(3)', (e) => {
38 | return e.textContent
39 | })
40 |
41 | console.log(color('[LOGS]', 'grey'), 'Cekringgg!')
42 | console.log(color('[LOGS]', 'grey'), { donatur: who, total: much, pesan: msg })
43 | client.sendText(ownerNumber, `Cekringgg!!\nDonatur: ${who}\nTotal: ${much}\nPesan: ${msg}`)
44 | if (msg.match(/chat\.whatsapp\.com/gi) !== null) {
45 | sewaBot(client, msg, 30).then(res => {
46 | if (res) client.sendText(ownerNumber, `[AUTO SEWA] Berhasil menyewakan bot selama 30 hari.`)
47 | else client.sendText(ownerNumber, `Gagal menyewakan bot!`)
48 | }).catch(e => {
49 | client.sendText(ownerNumber, e.toString())
50 | })
51 | }
52 | }).catch(e => reject(e))
53 |
54 | await page.evaluate(() => {
55 | const target = document.querySelector('div#__next')
56 | const observer = new MutationObserver(mutations => {
57 | for (const mutation of mutations) {
58 | if (mutation.type === 'childList') {
59 | // eslint-disable-next-line no-undef
60 | puppeteerLogMutation()
61 | }
62 | }
63 | })
64 | observer.observe(target, { childList: true })
65 | })
66 | resolve(true)
67 | } catch (e) {
68 | reject(e)
69 | }
70 | })
71 |
72 | // eslint-disable-next-line no-async-promise-executor
73 | const sewaBot = (client, linkGroup, duration) => new Promise(async (resolve, reject) => {
74 | try {
75 | db.read()
76 | let milis = duration * 86400000 //duration in day
77 | let isGroupId = linkGroup.endsWith('@g.us')
78 | let groupInfo = isGroupId ? { id: linkGroup } : await client.inviteInfo(linkGroup)
79 | const find = db.chain.get('groups').find({ groupId: groupInfo.id }).value()
80 | if (find && find.groupId === groupInfo.id) {
81 | if (!isGroupId) {
82 | client.joinGroupViaLink(linkGroup).catch(reject)
83 | }
84 | let dateBefore = new Date(find.expire)
85 | let dateAfter = dateBefore.getTime() + milis
86 | let expireAt = new Date(dateAfter)
87 | client.sendText(groupInfo.id, `Perubahan penyewaan bot berhasil!\nBot akan keluar sendiri pada hari ${expireAt.toLocaleDateString('id-ID', LOCAL_DATE_OPTIONS)}`)
88 | db.chain.get('groups').find({ groupId: groupInfo.id }).update('expire', () => expireAt).value()
89 | db.data = db.chain
90 | db.write()
91 | resolve(true)
92 | } else if (!isGroupId) {
93 | let expireAt = new Date(Date.now() + milis)
94 | await client.joinGroupViaLink(linkGroup)
95 | .then(async () => {
96 | if (groupInfo.id) {
97 | setTimeout(async () => {
98 | await client.sendText(groupInfo.id, `Penyewaan bot berhasil!\nBot akan keluar sendiri pada hari ${expireAt.toLocaleDateString('id-ID', LOCAL_DATE_OPTIONS)}`)
99 | await client.sendText(groupInfo.id, `Hai guys 👋 perkenalkan saya SeroBot. Untuk melihat perintah atau menu yang tersedia pada bot, kirim *${prefix}menu*. Tapi sebelumnya pahami dulu *${prefix}tnc*`)
100 | }, 2000)
101 | db.data.groups.push({ groupId: groupInfo.id, expire: expireAt })
102 | db.write()
103 | resolve(true)
104 | } else {
105 | reject(false)
106 | }
107 | }).catch(async (e) => {
108 | reject(e)
109 | return client.sendText(ownerNumber, 'Gagal! Sepertinya Bot pernah dikick dari group penyewa')
110 | })
111 | } else {
112 | let expireAt = new Date(Date.now() + milis)
113 | await client.sendText(groupInfo.id, `Perhatian!\nBot akan keluar sendiri pada hari ${expireAt.toLocaleDateString('id-ID', LOCAL_DATE_OPTIONS)}`)
114 | db.data.groups.push({ groupId: groupInfo.id, expire: expireAt })
115 | db.write()
116 | resolve(true)
117 | }
118 | } catch (e) {
119 | reject(e)
120 | }
121 | })
122 |
123 | // eslint-disable-next-line no-async-promise-executor
124 | const trialSewa = (client, linkGroup) => new Promise(async (resolve, reject) => {
125 | try {
126 | db.read()
127 | let milis = 7 * 86400000 //duration in 7 day
128 | let gInfo = await client.inviteInfo(linkGroup)
129 | const find = db.chain.get('groups').find({ groupId: gInfo.id }).value()
130 | if (find?.groupId == gInfo?.id) {
131 | client.joinGroupViaLink(linkGroup).catch(async (e) => {
132 | reject(e)
133 | })
134 | resolve(false)
135 | } else {
136 | let expireAt = new Date(Date.now() + milis)
137 | await client.joinGroupViaLink(linkGroup)
138 | .then(async () => {
139 | if (gInfo.id) {
140 | setTimeout(async () => {
141 | await client.sendText(gInfo.id, `Trial penyewaan bot berhasil!\nBot akan keluar sendiri pada hari ${expireAt.toLocaleDateString('id-ID', LOCAL_DATE_OPTIONS)}`)
142 | await client.sendText(gInfo.id, `Hai guys 👋 perkenalkan saya SeroBot. Untuk melihat perintah atau menu yang tersedia pada bot, kirim *${prefix}menu*. Tapi sebelumnya pahami dulu *${prefix}tnc*`)
143 | }, 2000)
144 | db.data.groups.push({ groupId: gInfo.id, expire: expireAt })
145 | db.write()
146 | resolve(true)
147 | } else {
148 | reject(`Error joinGroupViaLink trialSewa`)
149 | }
150 | }).catch(async (e) => {
151 | reject(e)
152 | })
153 | }
154 | } catch (e) {
155 | reject(e)
156 | }
157 | })
158 |
159 | const checkExpireSewa = (client) => new Promise((resolve, reject) => {
160 | try {
161 | db.read()
162 | let now = new Date()
163 | let oneDayAfterNow = new Date(Date.now() + 86400000)
164 | let { groups } = db.data
165 | groups.forEach(async (group) => {
166 | let dateExpire = new Date(group.expire)
167 | let { groupId } = group
168 | if (dateExpire <= now) {
169 | deleteSewa(groupId)
170 | let info = await client.getGroupInfo(groupId)
171 | await client.sendText(groupId, `‼️〘 Bye 〙‼️\nPenyewaan telah berakhir.\nTerima kasih telah menggunakan bot. Selamat tinggal 👋🏼🤩`)
172 | await client.sendText(ownerNumber, `Penyewaan untuk group dengan:\n-> \`\`\`Id :\`\`\` ${groupId}\n-> \`\`\`Name :\`\`\` ${info.title}\nTelah selesai.`)
173 | setTimeout(async () => {
174 | await client.leaveGroup(groupId)
175 | }, 2000)
176 | setTimeout(async () => {
177 | await client.deleteChat(groupId)
178 | }, 4000)
179 | } else if (dateExpire <= oneDayAfterNow) {
180 | client.sendText(groupId, `‼️〘 Notice 〙‼️\nPenyewaan bot akan berakhir pada hari: \n${dateExpire.toLocaleDateString('id-ID', LOCAL_DATE_OPTIONS)}.\nChat /owner untuk perpanjang.`)
181 | }
182 | })
183 | resolve(true)
184 | } catch (e) {
185 | reject(e)
186 | }
187 | })
188 |
189 | const deleteSewa = (id) => {
190 | db.read()
191 | let res = db.chain.get('groups').remove({ groupId: id }).value()
192 | db.data = db.chain
193 | db.write()
194 | return res.length == 0 ? false : true
195 | }
196 |
197 | // eslint-disable-next-line no-async-promise-executor
198 | const getListSewa = (client) => new Promise(async (resolve, reject) => {
199 | try {
200 | db.read()
201 | let { groups } = db.data
202 | groups = await groups.map(async (group) => {
203 | let { title } = await client.getGroupInfo(group.groupId)
204 | let date = new Date(group.expire)
205 | let expire = date.toLocaleDateString('id-ID', LOCAL_DATE_OPTIONS)
206 | return {
207 | title: title,
208 | groupId: group.groupId,
209 | expire: expire
210 | }
211 | })
212 | Promise.all(groups).then(res => {
213 | resolve(res)
214 | })
215 | } catch (e) {
216 | reject(e)
217 | }
218 | })
219 |
220 | const isSewa = (id) => {
221 | db.read()
222 | const find = db.chain.get('groups').find({ groupId: id }).value()
223 | return !!find
224 | }
225 |
226 | const getExp = (id) => {
227 | db.read()
228 | let msg = ''
229 | const find = db.chain.get('groups').find({ groupId: id }).value()
230 | if (find && find.groupId === id) {
231 | let date = new Date(find.expire)
232 | msg = date.toLocaleDateString('id-ID', LOCAL_DATE_OPTIONS)
233 | } else {
234 | msg = false
235 | }
236 | return msg
237 | }
238 | //Capek ngasih dokumentasi. lo pahamin aje sendiri
239 |
240 | export default {
241 | checkExpireSewa,
242 | listenSaweria,
243 | getListSewa,
244 | deleteSewa,
245 | trialSewa,
246 | sewaBot,
247 | getExp,
248 | isSewa
249 | }
--------------------------------------------------------------------------------
/lib/shortener.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: SeroBot Team
3 | * @ Create Time: 2021-05-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-07-05 13:48:21
6 | * @ Description: Shortener
7 | */
8 |
9 | import { fetchText } from '../utils/fetcher.js'
10 |
11 | /**
12 | * Create shorturl
13 | *
14 | * @param {String} url
15 | */
16 | const shortener = (url) => new Promise((resolve, reject) => {
17 | console.log(color('[LOGS]', 'grey'), 'Creating short url...')
18 | fetchText(`https://tinyurl.com/api-create.php?url=${url}`)
19 | .then((text) => resolve(text))
20 | .catch((err) => reject(err))
21 | })
22 |
23 | export default shortener
24 |
--------------------------------------------------------------------------------
/lib/tebak.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: SeroBot Team
3 | * @ Create Time: 2021-05-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-08-01 20:47:18
6 | * @ Description: Fun room crud
7 | */
8 |
9 | import appRoot from 'app-root-path'
10 | import lodash from 'lodash'
11 | import { LowSync, JSONFileSync } from 'lowdb'
12 | import axios from 'axios'
13 | import Crypto from 'crypto'
14 | import cheerio from 'cheerio'
15 | import fs from 'fs'
16 |
17 | const { get } = axios
18 | const { apiLol } = JSON.parse(fs.readFileSync(appRoot + '/settings/api.json'))
19 | const adapter = new JSONFileSync(appRoot + '/data/tebak.json')
20 | const db = new LowSync(adapter)
21 | db.read()
22 | db.data = { chats: [] } // refresh every session
23 | db.write()
24 | db.chain = lodash.chain(db.data)
25 |
26 | // eslint-disable-next-line no-unused-vars
27 | const scrapeTebakGambar = () => new Promise((resolve, reject) => {
28 | let baseUrl = 'https://jawabantebakgambar.net'
29 | let random = Crypto.randomInt(0, 2000)
30 | let endpoint = `${baseUrl}/id-${random}.html`
31 |
32 | get(endpoint).then(res => {
33 | let $ = cheerio.load(res.data)
34 | let imgUrl = $('div.content > ul.images').find('img').attr('src')
35 | let ans = $('div.content > ul.images').find('img').attr('alt')?.replace('Jawaban ', '')
36 |
37 | resolve({
38 | data: {
39 | result: {
40 | image: baseUrl + imgUrl,
41 | answer: ans
42 | }
43 | }
44 | })
45 | }).catch(err => reject(err))
46 | })
47 |
48 | /**
49 | * Get Tebak Gambar object from api
50 | * @param {String} chatId
51 | * @returns {Promise} `TebakGambar` object
52 | */
53 | const getTebakGambar = (chatId) => new Promise((resolve, reject) => {
54 | try {
55 | // axios.get(`https://lolhuman.herokuapp.com/api/tebak/gambar2?apikey=${apiLol}`)
56 | scrapeTebakGambar()
57 | .then((res) => {
58 | let ans = res.data.result.answer
59 | saveRoom(chatId, ans)
60 | resolve(res.data.result)
61 | }).catch((err) => {
62 | reject(err)
63 | })
64 | } catch (err) { reject(err) }
65 | })
66 |
67 | const getTebakKata = (chatId) => new Promise((resolve, reject) => {
68 | try {
69 | axios.get(`https://neoxr-api.herokuapp.com/api/games/whathis?apikey=yntkts`)
70 | .then((res) => {
71 | let ans = res.data.data.jawaban
72 | saveRoom(chatId, ans)
73 | resolve(res.data.data)
74 | })
75 | } catch (e) {
76 | reject(e)
77 | }
78 | })
79 |
80 | const getTebakLirik = (chatId) => new Promise((resolve, reject) => {
81 | try {
82 | axios.get(`https://lolhuman.herokuapp.com/api/tebak/lirik?apikey=${apiLol}`)
83 | .then((res) => {
84 | let ans = res.data.result.answer
85 | saveRoom(chatId, ans)
86 | resolve(res.data.result)
87 | })
88 | } catch (e) {
89 | reject(e)
90 | }
91 | })
92 |
93 | const getTebakJenaka = (chatId) => new Promise((resolve, reject) => {
94 | try {
95 | axios.get(`https://lolhuman.herokuapp.com/api/tebak/jenaka?apikey=${apiLol}`)
96 | .then((res) => {
97 | let ans = res.data.result.answer
98 | saveRoom(chatId, ans)
99 | resolve(res.data.result)
100 | })
101 | } catch (e) {
102 | reject(e)
103 | }
104 | })
105 |
106 | /**
107 | * Save ans of Tebak Room to database match chatId.
108 | * @param {String} chatId
109 | * @returns {Promise} true
110 | */
111 | const saveRoom = (chatId, ans) => new Promise((resolve, reject) => {
112 | try {
113 | const find = db.chain.get('chats').find({ id: chatId }).value()
114 | if (find && find.id === chatId) {
115 | db.chain.get('chats').find({ id: chatId }).set('ans', ans).value()
116 | db.write()
117 | resolve(true)
118 | } else {
119 | db.chain.get('chats').push({ id: chatId, ans: ans }).value()
120 | db.write()
121 | resolve(true)
122 | }
123 | } catch (e) {
124 | reject(e)
125 | }
126 | })
127 |
128 | /**
129 | * Get Ans of Tebak Room from database match chatId.
130 | * @param {String} chatId
131 | * @returns {Promise} `Ans` object | `false`
132 | */
133 | const getAns = (chatId) => new Promise((resolve, reject) => {
134 | try {
135 | const find = db.chain.get('chats').find({ id: chatId }).value()
136 | if (find && find.id === chatId) {
137 | const ans = db.chain.get('chats').find({ id: chatId }).value()
138 | resolve(ans)
139 | } else {
140 | resolve(false)
141 | }
142 | } catch (err) { reject(err) }
143 | })
144 |
145 | /**
146 | * Check room if exist from database match chatId.
147 | * @param {String} chatId
148 | * @returns {Promise} true/false
149 | */
150 | const isRoomExist = async (chatId) => !!(await getAns(chatId))
151 |
152 | /**
153 | * Delete Room data from database match chatId.
154 | * @param {String} chatId
155 | * @returns {Promise} Promise resolve `true` if success
156 | */
157 | const delRoom = (chatId) => new Promise((resolve, reject) => {
158 | try {
159 | const res = db.chain.get('chats').remove({ id: chatId }).value()
160 | db.write()
161 | if (res.length === 0) resolve(false)
162 | else resolve(true)
163 | } catch (err) { reject(err) }
164 | })
165 |
166 | // BY SEROBOT -> https://github.com/dngda/bot-whatsapp
167 |
168 | export default {
169 | getTebakGambar,
170 | getTebakJenaka,
171 | getTebakLirik,
172 | getTebakKata,
173 | isRoomExist,
174 | delRoom,
175 | getAns
176 | }
--------------------------------------------------------------------------------
/media/tes.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/media/tes.txt
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bot-whatsapp",
3 | "version": "3.6.1",
4 | "description": "Whatsapp Bot - Node Js",
5 | "main": "index.js",
6 | "type": "module",
7 | "scripts": {
8 | "start": "node index",
9 | "postinstall": "patch-package"
10 | },
11 | "author": "Danang Dwiyoga A",
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/dngda/bot-whatsapp.git"
15 | },
16 | "bugs": {
17 | "url": "https://github.com/dngda/bot-whatsapp/issues"
18 | },
19 | "homepage": "https://github.com/dngda/bot-whatsapp",
20 | "license": "Apache-2.0",
21 | "dependencies": {
22 | "@open-wa/wa-automate": "^4.7.1",
23 | "app-root-path": "^3.0.0",
24 | "axios": "^0.21.0",
25 | "canvas": "^2.8.0",
26 | "chalk": "^4.1.1",
27 | "cheerio": "^1.0.0-rc.9",
28 | "figlet": "^1.5.0",
29 | "file-type": "^16.4.0",
30 | "fluent-ffmpeg": "^2.1.2",
31 | "form-data": "^4.0.0",
32 | "free-translate": "^0.4.0",
33 | "fs-extra": "^10.0.0",
34 | "gtts": "^0.2.1",
35 | "jimp": "^0.16.1",
36 | "lodash": "^4.17.21",
37 | "lowdb": "^2.1.0",
38 | "mathjs": "^9.4.3",
39 | "moment-timezone": "^0.5.33",
40 | "node-fetch": "^2.6.1",
41 | "node-schedule": "^2.0.0",
42 | "office-to-pdf": "^4.0.0",
43 | "p-queue": "^7.1.0",
44 | "puppeteer-extra-plugin-stealth": "^2.7.8",
45 | "remove.bg": "^1.3.0",
46 | "request": "^2.88.2",
47 | "sharp": "^0.29.0",
48 | "update-json-file": "^1.1.1",
49 | "yt-search": "^2.8.0",
50 | "ytdl-core": "^4.8.3"
51 | },
52 | "devDependencies": {
53 | "eslint": "^7.29.0",
54 | "patch-package": "^6.4.7"
55 | },
56 | "optionalDependencies": {
57 | "bufferutil": "^4.0.3"
58 | },
59 | "directories": {
60 | "lib": "lib"
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/patches/fluent-ffmpeg+2.1.2.patch:
--------------------------------------------------------------------------------
1 | diff --git a/node_modules/fluent-ffmpeg/lib/processor.js b/node_modules/fluent-ffmpeg/lib/processor.js
2 | index 5a8e56d..d7fdf2f 100644
3 | --- a/node_modules/fluent-ffmpeg/lib/processor.js
4 | +++ b/node_modules/fluent-ffmpeg/lib/processor.js
5 | @@ -149,7 +149,7 @@ module.exports = function(proto) {
6 | var stderrClosed = false;
7 |
8 | // Spawn process
9 | - var ffmpegProc = spawn(command, args, options);
10 | + var ffmpegProc = spawn(command, args, {options, windowsHide: true});
11 |
12 | if (ffmpegProc.stderr) {
13 | ffmpegProc.stderr.setEncoding('utf8');
14 |
--------------------------------------------------------------------------------
/restart.cmd:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | FOR /f "tokens=2" %%a in ('
3 | tasklist /FI "IMAGENAME eq node.exe" ^| findstr /ic:"node.exe"
4 | ') Do SET pid=%%a
5 | START "Bot WhatsApp" node index
6 | taskkill /F /PID %pid%
--------------------------------------------------------------------------------
/settings/api.json.example:
--------------------------------------------------------------------------------
1 | {
2 | "apiNoBg": ["YOUR-API-KEY-HERE", "ADD-OTHER-API-KEY-HERE-FOR-MORE-LIMIT", "AND-AGAIN"],
3 | "apiFarzain": "YOUR-API-KEY-HERE",
4 | "apiItech": "YOUR-API-KEY-HERE",
5 | "apiLol": "YOUR-API-KEY-HERE",
6 | "apiGenius": "YOUR-API-KEY-HERE",
7 | "apiOcr": "YOUR-API-KEY-HERE",
8 | "saweriaOverlay": "YOUR SAWERIA OVERLAY LINK"
9 | }
--------------------------------------------------------------------------------
/settings/katakasar.json:
--------------------------------------------------------------------------------
1 | [
2 | "anjing",
3 | "kontol",
4 | "memek",
5 | "jembut",
6 | "bangsat",
7 | "ajg",
8 | "anj",
9 | "asu",
10 | "bajingan",
11 | "lonte",
12 | "kntl",
13 | "fuck",
14 | "fck",
15 | "anjg",
16 | "goblog",
17 | "bajigur",
18 | "kepet",
19 | "ancuk",
20 | "babi",
21 | "jancuk",
22 | "njg",
23 | "kontol",
24 | "jancok",
25 | "pantek",
26 | "panteq",
27 | "anying",
28 | "sundala",
29 | "telaso"
30 | ]
--------------------------------------------------------------------------------
/settings/nsfwquery.json:
--------------------------------------------------------------------------------
1 | [
2 | "sexy",
3 | "nude",
4 | "nudes",
5 | "memek",
6 | "kontol",
7 | "bugil",
8 | "topless",
9 | "telanjang",
10 | "tempik",
11 | "hentai",
12 | "colmek",
13 | "ngentot",
14 | "payudara",
15 | "bokep",
16 | "xxx",
17 | "toket",
18 | "porn",
19 | "porno",
20 | "oppai"
21 | ]
--------------------------------------------------------------------------------
/settings/setting.json:
--------------------------------------------------------------------------------
1 | {
2 | "ownerNumber": "628xxxxx@c.us",
3 | "memberLimit": 3,
4 | "groupLimit": 30,
5 | "prefix": "/",
6 | "groupOfc": "",
7 | "stickerHash": {
8 | "menu": "y75El/Dq8ktqPIlBM+L+JlJ7EJ69yJXBcRF+zv4ILCo=",
9 | "ping": "e7HHnS78G1dosTLMaLVxUhztWSHn/in+wWFML2BLw2E="
10 | }
11 | }
--------------------------------------------------------------------------------
/src/font/ChakraPetch-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/font/ChakraPetch-Bold.ttf
--------------------------------------------------------------------------------
/src/font/ChakraPetch-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/font/ChakraPetch-Regular.ttf
--------------------------------------------------------------------------------
/src/json/genshinbuild.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "ningguang",
4 | "build": "https://pbs.twimg.com/media/Em-fPLbXIAMeGHs.jpg"
5 | },
6 | {
7 | "name": "eula",
8 | "build": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRenIHog_Y7-RaY9xWmApOBXDHsnmp0GPfxBA&usqp=CAU"
9 | },
10 | {
11 | "name": "qiqi",
12 | "build": "https://i.pinimg.com/originals/a6/30/72/a630722d0b892f3726a8d6f5305a8d51.jpg"
13 | },
14 | {
15 | "name": "bennett",
16 | "build": "https://i.pinimg.com/originals/6f/45/f0/6f45f0c3a9fb25279dc8d27d91e68e04.jpg"
17 | },
18 | {
19 | "name": "ganyu",
20 | "build": "https://pbs.twimg.com/media/Erj5aqWXUAQWZoK.jpg"
21 | },
22 | {
23 | "name": "diluc",
24 | "build": "https://pbs.twimg.com/media/EnSynS8W4AQH58E.jpg"
25 | },
26 | {
27 | "name": "hutao",
28 | "build": "https://upload-os-bbs.mihoyo.com/upload/2021/03/05/63355475/6c6e0880deecb8724eb5782ce2abe326_7391460892029173849.png"
29 | },
30 | {
31 | "name": "klee",
32 | "build": "https://pbs.twimg.com/media/EnGJHUAXMAIuzKD.jpg"
33 | },
34 | {
35 | "name": "mona",
36 | "build": "https://i.pinimg.com/originals/b1/0b/4f/b10b4f74c40df78d86ffad813bf19b11.jpg"
37 | },
38 | {
39 | "name": "childe",
40 | "build": "https://pbs.twimg.com/media/Emtc2HBXYAMA58S.jpg"
41 | },
42 | {
43 | "name": "venti",
44 | "build": "https://pbs.twimg.com/media/EnojhCpXcAAAgeW.jpg"
45 | },
46 | {
47 | "name": "xiao",
48 | "build": "https://pbs.twimg.com/media/EtUpocpWgAov3gN.jpg"
49 | },
50 | {
51 | "name": "xingqiu",
52 | "build": "https://pbs.twimg.com/media/EveqXA5XEAgJW5Y.jpg"
53 | },
54 | {
55 | "name": "zhongli",
56 | "build": "https://pbs.twimg.com/media/EoREoPFW4AA1xlA.jpg"
57 | },
58 | {
59 | "name": "albedo",
60 | "build": "https://upload-os-bbs.mihoyo.com/upload/2020/12/28/63355475/47bc7b1162a21453f1220a374bf15da1_2193150447268650678.png"
61 | },
62 | {
63 | "name": "diona",
64 | "build": "https://pbs.twimg.com/media/EnJI-SiW8AEWACM.jpg"
65 | },
66 | {
67 | "name": "fischl",
68 | "build": "https://staticg.sportskeeda.com/editor/2021/03/04b93-16153802018217-800.jpg"
69 | },
70 | {
71 | "name": "jean",
72 | "build": "https://pbs.twimg.com/media/EmTrchHXEAA6IZa.jpg"
73 | },
74 | {
75 | "name": "keqing",
76 | "build": "https://i.pinimg.com/originals/7d/90/b9/7d90b94f5194b74c104686287216ccee.png"
77 | },
78 | {
79 | "name": "razor",
80 | "build": "https://upload-os-bbs.mihoyo.com/upload/2020/12/11/63355475/26034e7eb14a93af1e466cb9914afa89_5399551990996542927.png"
81 | },
82 | {
83 | "name": "rosaria",
84 | "build": "https://pbs.twimg.com/media/EyjQ3V5WQAQ6rYk.jpg"
85 | },
86 | {
87 | "name": "sucrose",
88 | "build": "https://pbs.twimg.com/media/EoBu7oQXUAMJjWL.jpg"
89 | },
90 | {
91 | "name": "xiangling",
92 | "build": "https://upload-os-bbs.hoyolab.com/upload/2020/11/21/63355475/5dd077533466cbbdc4087e72713bf5b6_4149424357349932943.png"
93 | },
94 | {
95 | "name": "barbara",
96 | "build": "https://pbs.twimg.com/media/Es_G80eXMAgHFq3.jpg"
97 | },
98 | {
99 | "name": "beidou",
100 | "build": "https://pbs.twimg.com/media/EmZTPl_WMAEmikq.jpg"
101 | },
102 | {
103 | "name": "chongyun",
104 | "build": "https://i.pinimg.com/originals/b3/b1/cc/b3b1cce69b592c9fbb590dbe8cbc6ba3.jpg"
105 | },
106 | {
107 | "name": "kaeya",
108 | "build": "https://pbs.twimg.com/media/ErVRuSrXUAYx3It.jpg"
109 | },
110 | {
111 | "name": "xinyan",
112 | "build": "https://upload-os-bbs.hoyolab.com/upload/2021/01/27/63355475/8d10c6784b158bc95e0aa60918217a34_1082325582054032291.png"
113 | },
114 | {
115 | "name": "lisa",
116 | "build": "https://upload-os-bbs.hoyolab.com/upload/2021/02/13/63355475/6718b2955f0f126e717121ef971c382a_8520390941442621949.png"
117 | },
118 | {
119 | "name": "noelle",
120 | "build": "https://pbs.twimg.com/media/Es8LXamXYAMZOVk.jpg"
121 | },
122 | {
123 | "name": "amber",
124 | "build": "https://upload-os-bbs.hoyolab.com/upload/2021/02/21/63355475/c24676965b33c9729e55d574317f4e4b_6012764714877069971.png"
125 | }
126 | ]
--------------------------------------------------------------------------------
/src/mov/wasted.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/mov/wasted.mov
--------------------------------------------------------------------------------
/src/png/ava.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/png/ava.png
--------------------------------------------------------------------------------
/src/png/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/png/bg.png
--------------------------------------------------------------------------------
/src/png/bgnight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/png/bgnight.png
--------------------------------------------------------------------------------
/src/png/group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/png/group.png
--------------------------------------------------------------------------------
/src/sfx/astaghfirullah.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/sfx/astaghfirullah.mp3
--------------------------------------------------------------------------------
/src/sfx/balebale.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/sfx/balebale.mp3
--------------------------------------------------------------------------------
/src/sfx/callambulance.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/sfx/callambulance.mp3
--------------------------------------------------------------------------------
/src/sfx/headshot.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/sfx/headshot.mp3
--------------------------------------------------------------------------------
/src/sfx/kekw.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/sfx/kekw.mp3
--------------------------------------------------------------------------------
/src/sfx/kuinginmarah.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/sfx/kuinginmarah.mp3
--------------------------------------------------------------------------------
/src/sfx/kumenangis.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/sfx/kumenangis.mp3
--------------------------------------------------------------------------------
/src/sfx/letsgo.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/sfx/letsgo.mp3
--------------------------------------------------------------------------------
/src/sfx/salam.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/sfx/salam.mp3
--------------------------------------------------------------------------------
/src/sfx/vacation.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/sfx/vacation.mp3
--------------------------------------------------------------------------------
/src/sfx/wtf.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dngda/bot-whatsapp/b633a2b7dce42450fa39082c3ccd9e402c6083de/src/sfx/wtf.mp3
--------------------------------------------------------------------------------
/src/txt/dare.txt:
--------------------------------------------------------------------------------
1 | Ajak orang yang tidak kamu kenal untuk selfie berdua dengan mu lalu upload ke snapgram
2 | Ambil beberapa nomor dari kontakmu secara acak dan kirim chat "Aku hamil" sama mereka.
3 | Ambil minuman apa saja yang ada didekat mu lalu campurkan dengan cabai dan minum!
4 | Ambil nomor secara acak dari kontakmu, telepon dia, dan bilang "Aku mencintaimu"
5 | Beli makanan paling murah di kantin (atau beli sebotol aqua) dan bilang sambil tersedu-sedu pada teman sekelasmu "Ini.adalah makanan yang paling mahal yang pernah kubeli"
6 | Beli satu botol coca cola dan siram bunga dengan coca cola itu di depan orang banyak.
7 | Berdiri deket kulkas, tutup mata, pilih makanan secara acak didalemnya, pas makanpun mata harus tetep ditutup.
8 | Berdiri di tengah lapangan basket dan berteriak, "AKU MENCINTAIMU PANGERANKU/PUTRIKU"
9 | Beri hormat pada seseorang di kelas, lalu bilang "Hamba siap melayani Anda, Yang Mulia."
10 | Berjalan sambil bertepuk tangan dan menyanyi lagu "Selamat Ulang Tahun" dari kelas ke koridor.
11 | Berlutut satu kaki dan bilang "Marry me?" sama orang pertama yang masuk ke ruangan.
12 | Bikin hiasan kepala absurd dari tisu, apapun itu, terus suruh pose didepan kamera, terus upload
13 | Bilang "KAMU CANTIK/GANTENG BANGET NGGAK BOHONG" sama cewek yang menurutmu paling cantik di kelas ini
14 | Bilang pada seseorang di kelas, "Aku baru saja diberi tahu aku adalah kembaranmu dulu, kita dipisahkan, lalu aku menjalani operasi plastik. Dan ini adalah hal paling serius yang pernah aku katakan."
15 | Buang buku catatan seseorang ke tempat sampah, di depan matanya, sambil bilang "Buku ini isinya tidak ada yang bisa memahami"
16 | Cabut bulu kaki mu sendiri sebanyak 3 kali!
17 | Chat kedua orangtuamu, katakan bahwa kamu kangen dengan mereka lengkap dengan emoticon sedih.
18 | Coba searcing google mengenai hal-hal yang mengerikan atau menggelikan seperti trypophobia, dll.
19 | Duduk relaks di tengah lapangan basket sambil berpura-pura itu adalah pantai untuk berjemur.
20 | isi mulut penuh dengan air dan harus tahan hingga dua putaranJika tertawa dan tumpah atau terminum, maka harus ngisi ulang dan ditambah satu putaran lagi.
21 | Salamanlah dengan orang pertama yang masuk ke ruangan ini dan bilang "Selamat datang di Who Wants To Be a Millionaire!"
22 | Kirim chat pada orangtuamu "Hai, bro! Aku baru beli majalah Playboy edisi terbaru!"
23 | Kirim chat pada orangtuamu, "Ma, Pa, aku sudah tahu bahwa aku adalah anak adopsi dari Panti Asuhan. Jangan menyembunyikan hal ini lagi."
24 | Kirim chat pada tiga nomor acak di kontakmu dan tulis "Aku baru saja menjadi model majalah Playboy."
25 | Makan satu sendok makan kecap manis dan kecap asin!
26 | Makan sesuatu tapi gak pake tangan.
27 | Marah-marahi ketemen kamu yang gak dateng padahal udah janjian mau main "truth or dare" bareng"
28 | Pecahkan telur menggunakan kepala!
29 | Makanlah makanan yang sudah dicampur-campur dan rasanya pasti aneh, namun pastikan bahwa makanan itu tidak berbahaya untuk kesehatan jangka panjang maupun jangka pendek.
30 | Menari ala Girls Generation untuk cowok di depan kelas, atau menari ala Super Junior untuk cewek.
31 | Mengerek tiang bendera tanpa ada benderanya.
32 | Menggombali orang yang ditaksir, sahabat terdekat, lawan jenis yang tidak dikenal sama sekali dan sejenisnya.
33 | Meniru style rambut semua temen kamu.
34 | Menyanyikan lagu HAI TAYO di depan banyak orang sambil menari
35 | Menyanyikan lagu Baby Shark dengan keras di ruang kelas.
36 | Minjem sesuatu ke tetangga
37 | Minta tandatangan pada seorang guru yang paling paling galak sambil bilang "Anda benar-benar orang yang paling saya kagumi di dunia."
38 | Minta uang pada seseorang (random/acak) di jalan sambil bilang "Saya tidak punya uang untuk naik angkot."
39 | Minum sesuatu yang udah dibuat/disepakatin, tapi pastiin gak berbahaya, bisa kayak minum sirup yang digaremin terus ditambah kecap.
40 | Ngomong ke gebetannya emoticon-Takut, ngobrol ngalurngidul apapun lah boleh ,via manapun juga bisa.
41 | Nyanyi-nyanyi lagu favorit difilm disney diluar rumah sambil teriak-teriak.
42 | Nyebutin 1 biru sampai 20 biru dengan cepat dan tidak boleh melakukan kesalahan. Jika salah maka harus diulang dari awal.
43 | Pakai mahkota tiruan dari kertas buku dan bilang sama setiap orang di ruangan "BERI PENGHORMATAN PADA YANG MULIA RAJA" sambil menunjuk setiap orang dengan penggaris.
44 | Pake celana kebalik sampe besok paginya.
45 | Peluk orang yang NGGAK kamu sukai di kelas dan bilang, "Terimakasih banyak kamu sudah bersedia menjadi orang paling baik untukku."
46 | Pergi ke lapangan yang luas, lalu berlari sekencang kencangnya sambil mengatakan “aku gila aku gila”
47 | Petik bunga lalu tancapkan bunga itu ke orang yang tidak kamu kenal (harus lawan jenis ya)
48 | Pilih orang secara acak di jalan, lalu bilang "You dont know youre beautiful" (ala One Direction)
49 | Pura pura kerasukan ex: kerasukan macan dll
50 | Suruh bersiul pas mulutnya lagi penuh dijejelin makanan.
51 | Suruh jadi pelayan buat ngelayanin kamu sama temen-temen kamu buat makan siang.
52 | Suruh pake kaos kaki buat dijadiin sarung tangan.
53 | Suruh pake topi paling aneh/helm paling absurd selama putaraann kedepan.
54 | Telpon mama kamu dan bilang “ma, aku mau nikah secepatnya”
55 | Telpon mantan kamu dan bialng “aku rindu kamu”
56 | Tuker baju sama orang terdekat sampe ronde berikutnya.
57 | Update status di BBM, Line, WA, atau apapun itu dengan kata kata yang semuanya berawalan "S"
58 | Upload video nyanyi ke youtube yang lagi nyanyiin lagu-lagu populer
59 | Warnain kuku kaki dan tangan tapi dengan warna berbeda-beda buat seminggu.
60 | Makan 2 sendok nasi tanpa lauk apapun, kalo seret boleh minum.
61 | Spill orang yang bikin kamu jedag jedug.
62 | Telfon crush/pacar sekarang dan ss ke pemain.
63 | Drop emot "🤡" setiap ngetik di gc/pc selama 1 hari.
64 | Ucapin kata "Selamat datang di Who Wants To Be a Millionaire!" ke semua grup yang kamu punya.
65 | Marah² ga jelas ke penonton sw kamu urutan 30.
66 | Telfon mantan bilang kangen.
67 | Nyanyiin reff lagu yang terakhir kamu setel.
68 | VN mantan/crush/pacar kamu, bilang hi (namanya), mau telfon dong, bentar ajaa. aku kangen🥺👉🏼👈🏼".
69 | kletekan di meja (yg ada dirumah) sampe lo dimarahin karena berisik.
70 | belanjain (grab/gofood) buat salah satu pemain disini, terserah siapa. budget dibawah 25k.
71 | Bilang ke random people "Aku baru saja diberi tahu aku adalah kembaranmu dulu, kita dipisahkan, lalu aku menjalani operasi plastik. Dan ini adalah hal paling serius yang pernah aku katakan."
72 | Nebutin nama nama mantan.
73 | Buatin 1 pantun untuk pemain pertama!
74 | SS chat wa.
75 | Chat random people dengan bahasa alay lalu ss kesini
76 | Ceritain hal memalukan versi diri sendiri
77 | Tag orang yang dibenci
78 | Pura pura kerasukan, contoh : kerasukan maung, kerasukan belalang, kerasukan kulkas, dll.
79 | Ganti nama jadi " BOWO " selama 24 jam
80 | Teriak " anjimm gabutt anjimmm " di depan rumah mu
81 | Snap/post foto pacar/crush
82 | Sebutkan tipe pacar mu!
83 | Bilang "i hv crush on you, mau jadi pacarku gak?" ke lawan jenis yang terakhir bgt kamu chat (serah di wa/tele), tunggu dia bales, kalo udah SS.
84 | Record voice baca surah al-kautsar
85 | Prank chat mantan dan bilang " i love u, pgn balikan. " Tanpa ada kata dare!
86 | Chat ke kontak wa urutan sesuai %batre kamu, terus bilang ke dia "i lucky to hv you!"
87 | Ganti nama menjadi "gue anak lucinta luna" selama 5 jam
88 | Ketik pake bahasa sunda 24 jam
89 | Pake foto sule sampe 3 hari
90 | Drop kutipan lagu/quote, terus tag member yang cocok buat kutipan itu
91 | Kirim voice note bilang `can i call u baby`?
92 | SS recent call whatsapp
93 | Bilang "KAMU CANTIK BANGET NGGAK BOHONG" ke cowo!
94 | PAP ke salah satu anggota grup.
--------------------------------------------------------------------------------
/src/txt/skripsi.txt:
--------------------------------------------------------------------------------
1 | Udahlah, ngapain juga ngerjain skripsi, mending Valorant aja sampe Meninggoyy
2 | Teman-temanmu sudah kerja di e-commerce masa kamu masih skripsian
3 | out of topic, kenapa ya tulisan dosen pembimbing susah dibaca
4 | Hari yang cerah tuk mengerjakan skripsiku
5 | Bapakmu ra kuat mbayar ukt meneh le, skripsine ndang digarap
6 | Dosen pembimbingnya dichat lagi ayo
7 | Bengong mulu, skripsimu cok
8 | Mau sampai kapan kau diamkan skripsimu?
9 | Yok bisa yok dicicil skripsinya
10 | Kurangi skripsi, lanjutin rebahan
11 | Daripada ngerjain skripsi, mending kita mabar saja skuy
12 | Tetap menyerah, dan jangan semangat
13 | Mendung-mendung mending skripsian
14 | Apa tidak malu kepada mereka yang sudah selesai ujian kamu malah rebahan
15 | Waktu malmingmu hampir habis anak-anak, kembali kerjakan skripsimu!
--------------------------------------------------------------------------------
/src/txt/truth.txt:
--------------------------------------------------------------------------------
1 | Acara TV apa yang paling kamu benci? Berikan alasannya!
2 | Apa baju yang (menurutmu) paling jelek yang pernah kamu pakai, dan kapan kamu memakainya?
3 | Apa hal paling buruk (gosip) yang pernah kamu bilang tentang temenmu?
4 | Apa hal paling memalukan dari dirimu?
5 | Apa hal paling memalukan dari temanmu?
6 | Apa hal pertama yang kamu lihat saat kamu melihat orang lain (lawan jenis)?
7 | Apa hal pertama yang terlintas di pikiranmu saat kamu melihat cermin?
8 | Apa hal terbodoh yang pernah kamu lakukan?
9 | Apa ketakutan terbesar kamu?
10 | Apa mimpi terburuk yang pernah kamu alami?
11 | Apa mimpi terkonyol yang sampai sekarang kamu kamu ingat?
12 | Apa pekerjaan paling konyol yang pernah kamu bayangin kamu akan jadi?
13 | Apa sifat terburukmu menurut kamu?
14 | Apa sifat yang ingin kamu rubah dari dirimu?
15 | Apa sifat yang ingin kamu rubah dari temanmu?
16 | Apa yang akan kamu lakuin bila pacarmu bilang hidung atau jarimu jelek?
17 | Apa yang kamu fikirkan sebelum kamu tidur ? ex: menghayal tentang jodoh,dll.
18 | Apakah hal yang menurutmu paling menonjol dari dirimu?
19 | Bagian tubuh temanmu mana yang paling kamu sukai dan ingin kamu punya?
20 | Bagian tubuhmu mana yang paling kamu benci?
21 | Dari semua kelas yang ada di sekolah, kelas mana yang paling ingin kamu masuki dan kelas mana yang paling ingin kamu hindari?
22 | Deksripsikan teman terdekat mu!
23 | Deskripsikan dirimu dalam satu kata!
24 | Film dan lagu apa yang pernah membuat kamu menangis?
25 | Hal apa yang kamu rahasiakan sampe sekarang dan gak ada satu orangpun yang tau?
26 | Hal paling romantis apa yang seseorang (lawan jenis) pernah lakuin atau kasih ke kamu?
27 | Hal-hal menjijikan apa yang pernah kamu alami ?
28 | Jika kamu lahir kembali dan harus jadi salah satu dari temanmu, siapa yang akan kamu pilih untuk jadi dia?
29 | Jika punya kekuatan super/ super power ingin melakukan apa
30 | Jika sebentar lagi kiamat, apa yang kamu lakukan ?
31 | Kalo kamu disuruh operasi plastik dengan contoh wajah dari teman sekelasmu, wajah siapa yang akan kamu tiru?
32 | Kamu pernah mencuri sesuatu gak?
33 | Apakah kamu takut mati? kenapa?
34 | Kapan terakhir kali kamu menangis dan mengapa?
35 | Apa kemampuan spesial kamu apa?
36 | Kok bisa suka sama orang yang kamu sukai?
37 | Menurutmu, apa sifat baik teman terdekatmu yang nggak dia sadari?
38 | Orang seperti apa yang ingin kamu nikahi suatu saat nanti?
39 | Pekerjaan paling ngenes apa yang menurutmu cocok untuk teman yang sedang duduk di sebelahmu? Dan kenapa?
40 | Pengen tukeran hidup sehari dengan siapa? (teman terdekat yang kalian sama-sama tahu) dan mengapa
41 | Pernahkah kamu diam-diam berharap hubungan seseorang dengan pacarnya putus? Siapa?
42 | Pilih PACAR atau TEMAN ? Why?
43 | Quote apa yang paling kamu ingat dan kamu suka?
44 | Rahasia apa yang belum pernah kamu katakan sampai sekarang kepada teman mu?
45 | Siapa panutan yang benar-benar menjadi panutanmu?
46 | Siapa di antara temanmu yang kamu pikir matre?
47 | Siapa di antara teman-temanmu yang menurutmu potongan rambutnya paling nggak banget?
48 | Siapa diantara temen-temenmu yang paling NGGAK fotogenik dan kalo difoto lagi ketawa mukanya jelek banget?
49 | Siapa mantan terindah mu? dan mengapa kalian putus?
50 | Siapa nama artis yang pernah kamu bucinin diam-diam?
51 | Siapa nama guru cowok yang pernah kamu sukai dulu?
52 | Siapa nama mantan pacar teman mu yang pernah kamu sukai diam diam?
53 | Siapa nama orang (lawan jenis) yang menurutmu akan asyik bila dijadikan pacar?
54 | Siapa nama orang yang kamu benci, tapi kamu rasa orang itu suka sama kamu (nggak harus lawan jenis)?
55 | Siapa nama orang yang pernah kamu kepoin diam-diam?
56 | Siapa orang (lawan jenis) yang paling sering terlintas di pikiranmu?
57 | Siapa orang yang paling menjengkelkan di antara teman teman mu ? alasannya!
58 | Siapa sebenernya di antara teman-temanmu yang kamu pikir harus di make-over?
59 | Siapa yang paling mendekati tipe pasangan idealmu di sini?
60 | Ayah atau ibu?
61 | Bagian tubuh yang kamu tidak suka?
62 | Suka ilfil tentang apa?
63 | Pernah selingkuh?
64 | Pernah ciuman ?
65 | Pacaran paling sebentar berapa hari/bulan/tahun ?
66 | Apa hal pertama yang akan Anda lakukan jika Anda bangun sebagai lawan jenis?
67 | Pernahkah Anda membiarkan orang lain mendapat masalah karena sesuatu yang Anda lakukan?
68 | Apa hal paling memalukan yang pernah Anda lakukan?
69 | Apa alasan paling konyol bahwa Anda pernah putus dengan seseorang?
70 | Apa kebiasaan paling buruk yang Anda miliki?
71 | Menurut Anda apa fitur terbaik Anda? Dan apa yang terburuk?
72 | Apa hal paling berani yang pernah kamu lakukan?
73 | Siapa di group yang ingin kamu enchant jadi babi?
74 | Kapan terakhir kali Anda mengompol?
75 | Apa yang paling kamu impikan dari tidur?
76 | Jika Anda akan menghasilkan uang secara ilegal, bagaimana Anda membuatnya?
77 | Apa yang kekanak-kanakan yang masih Anda lakukan?
78 | Jika Anda buta, siapa yang akan menjadi anjing pemandu Anda?
79 | Apa yang paling mengesankan Anda?
80 | Jika Anda diizinkan untuk menggunakan hanya 3 kata untuk sisa malam mulai sekarang - yang mana itu?
81 | Jika Anda seorang diktator, hukum mana yang akan Anda undang terlebih dahulu?
82 | Jika Anda hidup selama era Nazi, siapa Anda?
83 | Apa pengalaman paling memalukan di waktu sekolah / waktu belajar / pendidikan / tahun lalu?
84 | Apa kesalahan terbesar dalam hidup Anda?
85 | Apa yang tidak akan pernah Anda lakukan - bahkan jika Anda tahu Anda hanya memiliki 12 jam lagi untuk hidup?
86 | Pelanggaran apa yang telah Anda lakukan?
87 | Ceritakan padaku rahasia dari masa kecilmu.
88 | Apa wakil (rahasia) terbesar Anda?
89 | Apa yang ingin Anda lakukan dengan saya … (atau orang xy), jika Anda kemudian dapat menghapus ingatannya (dia, …)?
90 | Apa hal terburuk yang pernah Anda lakukan kepada siapa pun?
91 | Siapa yang paling kamu sukai?
92 | Pernahkah Anda jatuh cinta dengan salah satu yang hadir?
93 | Jika Anda seorang vampir, siapa di antara kita yang akan Anda gigit sekarang?
94 | Apa hal terburuk yang pernah Anda alami?
95 | Apa keranjang terburukmu?
96 | Apakah Anda pernah buang air besar di depan umum?
97 | Apa fantasi tergelapmu?
98 | Apa hal terbaik yang pernah Anda alami dengan orang lain?
99 | Apa turn-off terbesar bagi Anda?
100 | Apa yang paling Anda sukai dari tubuh Anda dan apa yang paling jelek?
101 | Siapa dari ronde kami yang ingin kamu lihat telanjang?
102 | Siapa di babak ini yang bisa membuatmu jatuh cinta?
103 | Pernahkah Anda memiliki mimpi erotis di mana seseorang dari babak ini terjadi?
104 | Jika Anda akan menato diri Anda di area punggung - apa yang akan ada di sana?
105 | Apa yang lebih penting dalam suatu hubungan - seks atau cinta?
106 | Apakah Anda pikir seks itu keren, bagus, oke, kadang-kadang menyenangkan - atau tidak begitu penting bagi Anda?
107 | Apa yang membuat Anda benar-benar bercinta?
108 | Berapa kali seminggu / bulan berhubungan seks - dan seberapa sering Anda ingin berhubungan seks?
109 | Berapa banyak pasangan seks yang telah Anda tiduri?
110 | Bagian tubuh manakah yang paling membuat Anda?
111 | Bagaimana, di mana dan dengan siapa Anda pertama kali?
112 | Seberapa pentingkah foreplay yang diperluas untuk Anda?
113 | Apa yang harus dilakukan pria / wanita untuk menggoda Anda?
114 | Pernahkah Anda bertiga? Dan bagaimana Anda menyukainya?
115 | Pernahkah Anda berhubungan seks dengan teman baik?
116 | Apakah Anda pernah berhubungan seks dengan salah satu kelompok ini - kecuali pasangan Anda?
117 | Hewan apa yang paling cocok untukmu dan mengapa?
118 | Apa kesan pacaran terburukmu?
119 | Siapa yang ingin kamu cium sekarang?
120 | Apa rahasia kamu, fantasi gelap?
121 | Apakah Anda lebih suka tato pantat Anda atau menusuk lidah Anda?
122 | Apakah kamu selalu setia?
123 | Apakah Anda memiliki naksir remaja?
124 | Di orang mana kamu jatuh cinta?
125 | Selebritas mana yang ingin kamu kencani?
126 | Apa waasa saat paling memalukan dalam hidup Anda?
127 | Mulut mana yang paling Anda sukai dari grup di sini?
128 | Pemain mana yang memiliki tangan paling indah?
129 | Di mana ciuman pertamamu?
130 | Siapa di group ini yang paling ingin Anda cium?
131 | Siapa di group ini yang paling anda benci?
132 | Apa kesalahan terbesar dalam hidup Anda?
133 | Apakah sesuatu yang memalukan terjadi pada Anda berkencan?
134 | Apakah Anda pernah melakukan kontak dengan narkoba?
135 | Orang mana yang ingin kamu cium sekarang?
136 | Kapan terakhir kali Anda mabuk?
137 | Pernahkah kamu selingkuh saat ujian sekolah?
138 | Pernahkah kamu mencuri sesuatu di masa lalu?
139 | Apakah kamu mendengkur di malam hari?
140 | Yang manakah lagu favoritmu?
141 | Dengan pemain mana Anda akan bertukar selama 1 minggu dan mengapa?
142 | Anda pindah ke pulau yang sepi, siapa yang Anda bawa dari sini?
143 | Apa yang paling kamu takuti?
144 | Di mana Anda bercukur di mana-mana?
145 | Apakah Anda memiliki nama panggilan?
146 | Apakah Anda melihat poop Anda sebelum menyiramnya?
147 | Siapa yang memberimu sakit hati terburuk?
148 | Berapa kali kamu dighosting?
149 | Apa hal paling memalukan yang pernah terjadi padamu?
150 | Berapa banyak tipe / cewek yang sudah kamu cium?
151 | Kamu jatuh cinta dengan siapa?
152 | Bintang mana yang kamu sukai?
153 | Apakah Anda memulai sesuatu dengan XY (masukkan nama)?
154 | Pernahkah kamu mencuri sesuatu?
--------------------------------------------------------------------------------
/utils/fetcher.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-async-promise-executor */
2 | /**
3 | * @ Author: ArugaZ/YogaSakti
4 | * @ Create Time: 2021-05-31 22:33:11
5 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
6 | * @ Modified time: 2021-07-09 13:31:29
7 | * @ Description:
8 | */
9 |
10 | import fetch from 'node-fetch'
11 | import FormData from 'form-data'
12 | import { writeFile, readFileSync, unlinkSync } from 'fs'
13 | import fileType from 'file-type'
14 | import resizeImage from './resizeImage.js'
15 |
16 | const { fromBuffer } = fileType
17 |
18 | /**
19 | *Fetch Json from Url
20 | *
21 | *@param {String} url
22 | *@param {Object} options
23 | */
24 | const fetchJson = (url, options) =>
25 | new Promise((resolve, reject) =>
26 | fetch(url, options)
27 | .then(response => response.json())
28 | .then(json => resolve(json))
29 | .catch(err => {
30 | console.error(err)
31 | reject(err)
32 | })
33 | )
34 |
35 | /**
36 | * Fetch Text from Url
37 | *
38 | * @param {String} url
39 | * @param {Object} options
40 | */
41 |
42 | const fetchText = (url, options) => new Promise(async (resolve, reject) => {
43 | try {
44 | const response = await fetch(url, options)
45 | const text = await response.text()
46 | return resolve(text)
47 | } catch (err) {
48 | console.error(err)
49 | reject(err)
50 | }
51 | })
52 |
53 | /**
54 | * Fetch base64 from url
55 | * @param {String} url
56 | */
57 | const fetchBase64 = (url, mimetype) => new Promise(async (resolve, reject) => {
58 | try {
59 | const res = await fetch(url)
60 | const _mimetype = mimetype || res.headers.get('content-type')
61 | res.buffer()
62 | .then((result_1) => resolve(`data:${_mimetype};base64,` + result_1.toString('base64')))
63 | } catch (err) {
64 | console.error(err)
65 | reject(err)
66 | }
67 | })
68 |
69 | /**
70 | * Upload Image to Telegra.ph
71 | *
72 | * @param {String} base64 image buffer
73 | * @param {Boolean} resize
74 | */
75 | const uploadImages = (buffData, resize) => new Promise(async (resolve, reject) => {
76 | const { ext } = await fromBuffer(buffData)
77 | const filePath = './media/tmp.' + ext
78 | const _buffData = resize ? await resizeImage(buffData, false) : buffData
79 | writeFile(filePath, _buffData, { encoding: 'base64' }, (err) => {
80 | if (err) return reject(err)
81 | // console.log('Uploading image to telegra.ph server...')
82 | const fileData = readFileSync(filePath)
83 | const form = new FormData()
84 | form.append('file', fileData, 'tmp.' + ext)
85 | fetch('https://telegra.ph/upload', {
86 | method: 'POST',
87 | body: form
88 | })
89 | .then(res => res.json())
90 | .then(res => {
91 | if (res.error) return reject(res.error)
92 | resolve('https://telegra.ph' + res[0].src)
93 | })
94 | .then(() => unlinkSync(filePath))
95 | .catch(e => reject(e))
96 | })
97 | })
98 |
99 | export {
100 | fetchJson,
101 | fetchText,
102 | fetchBase64,
103 | uploadImages
104 | }
--------------------------------------------------------------------------------
/utils/index.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | /**
3 | * @ Author: SeroBot Team
4 | * @ Create Time: 2021-05-31 22:33:11
5 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
6 | * @ Modified time: 2021-07-19 00:07:48
7 | * @ Description:
8 | */
9 |
10 | import request from 'request'
11 | import fs from 'fs-extra'
12 | import chalk from 'chalk'
13 | import moment from 'moment-timezone'
14 | import updateJson from 'update-json-file'
15 | import Ffmpeg from 'fluent-ffmpeg'
16 |
17 | const { tz, duration } = moment
18 | const { head } = request
19 | const { existsSync, unlinkSync, readFileSync, createWriteStream, writeFileSync } = fs
20 | const { apiLol } = JSON.parse(readFileSync('./settings/api.json'))
21 |
22 | tz.setDefault('Asia/Jakarta').locale('id')
23 |
24 | /**
25 | * Get text with color
26 | * @param {String} text
27 | * @param {String} color
28 | * @return {String} Return text with color
29 | */
30 | const _color = (text, color) => {
31 | return !color ? chalk.blueBright(text) : chalk.keyword(color)(text)
32 | }
33 |
34 | const commandLog = (count) => updateJson('data/stat.json', (data) => {
35 | data['todayHits'] = count
36 | return data
37 | })
38 |
39 | const receivedLog = (count) => updateJson('data/stat.json', (data) => {
40 | data['received'] = count
41 | return data
42 | })
43 |
44 | /**
45 | * Get Time duration
46 | * @param {Date} timestamp
47 | * @param {Date} now
48 | */
49 | const processTime = (timestamp, now) => {
50 | // timestamp => timestamp when message was received
51 | return duration(now - moment(timestamp * 1000)).asSeconds()
52 | }
53 |
54 | /**
55 | * is it url?
56 | * @param {String} url
57 | */
58 | const isUrl = (url) => {
59 | 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))
60 | }
61 |
62 | // Message Filter / Message Cooldowns
63 | const usedCommandRecently = new Set()
64 |
65 | /**
66 | * Check is number filtered
67 | * @param {String} from
68 | */
69 | const isFiltered = (from) => {
70 | return !!usedCommandRecently.has(from)
71 | }
72 |
73 | /**
74 | * Add number to filter
75 | * @param {String} from
76 | */
77 | const addFilter = (from, delay) => {
78 | usedCommandRecently.add(from)
79 | setTimeout(() => {
80 | return usedCommandRecently.delete(from)
81 | }, delay) // 1sec is delay before processing next command
82 | }
83 |
84 | /**
85 | *Download any media from URL
86 | *@param {String} url
87 | *@param {Path} locate
88 | *@param {Callback} callback
89 | */
90 | const download = (url, path, callback) => {
91 | head(url, () => {
92 | request(url)
93 | .pipe(createWriteStream(path))
94 | .on('close', callback)
95 | })
96 | }
97 |
98 | const createReadFileSync = (path) => {
99 | if (existsSync(path)) {
100 | return readFileSync(path)
101 | }
102 | else {
103 | writeFileSync(path, '[]')
104 | return readFileSync(path)
105 | }
106 | }
107 |
108 | const formatin = (duit) => {
109 | let reverse = duit.toString().split('').reverse().join('')
110 | let ribuan = reverse.match(/\d{1,3}/g)
111 | ribuan = ribuan.join('.').split('').reverse().join('')
112 | return ribuan
113 | }
114 |
115 | const inArray = (needle, haystack) => {
116 | let length = haystack.length
117 | for (let i = 0; i < length; i++) {
118 | if (haystack[i].id == needle) return i
119 | }
120 | return -1
121 | }
122 |
123 | const last = (array, n) => {
124 | if (array == null) return void 0
125 | if (n == null) return array[array.length - 1]
126 | return array.slice(Math.max(array.length - n, 0))
127 | }
128 |
129 | const unlinkIfExists = (path, path2) => {
130 | if (existsSync(path)) unlinkSync(path)
131 | if (existsSync(path2)) unlinkSync(path2)
132 | }
133 |
134 | String.prototype.toDHms = function () {
135 | var sec_num = parseInt(this, 10) // don't forget the second param
136 | var hours = Math.floor(sec_num / 3600)
137 | var minutes = Math.floor((sec_num - (hours * 3600)) / 60)
138 | var seconds = sec_num - (hours * 3600) - (minutes * 60)
139 | var days = 0
140 | if (hours >= 24) { days = Math.floor(hours / 24); hours = hours % 24 }
141 | return days + ' days ' + hours + ' hours ' + minutes + ' minutes ' + seconds + ' secs'
142 | }
143 |
144 | const webpToPng = (buff) => new Promise((resolve, reject) => {
145 | const inp = `./media/sss.webp`
146 | const out = `./media/sss.png`
147 | writeFileSync(inp, buff)
148 | Ffmpeg(inp)
149 | .setFfmpegPath('./bin/ffmpeg')
150 | .save(out)
151 | .on('end', () => {
152 | resolve(readFileSync(out))
153 | })
154 | .on('error', (e) => {
155 | reject(e)
156 | })
157 | })
158 |
159 | const sleep = (delay) => new Promise((resolve) => {
160 | setTimeout(() => { resolve(true) }, delay)
161 | })
162 |
163 | const lolApi = (slash, parm = { text: null, text2: null, text3: null, img: null }) => {
164 | let ptext = (parm.text != null) ? `&text=${encodeURIComponent(parm.text)}` : ''
165 | let ptext2 = (parm.text2 != null) ? `&text=${encodeURIComponent(parm.text2)}` : ''
166 | let ptext3 = (parm.text3 != null) ? `&text=${encodeURIComponent(parm.text3)}` : ''
167 | let pimg = (parm.img != null) ? `&img=${parm.img}` : ''
168 | return `https://lolhuman.herokuapp.com/api/${slash}?apikey=${apiLol}${ptext}${ptext2}${ptext3}${pimg}`
169 | }
170 |
171 | // previous cmd
172 | let previousCmds = []
173 | const prev = {
174 | savePrevCmd: (inpSender, prevCmd) => {
175 | if (!prev.hasPrevCmd(inpSender)) {
176 | previousCmds.push({ sender: inpSender, prevCmd: prevCmd })
177 | setTimeout(() => {
178 | prev.delPrevCmd(inpSender)
179 | }, 15000)
180 | }
181 | },
182 | getPrevCmd: (inpSender) => {
183 | return previousCmds.find(n => n.sender == inpSender).prevCmd
184 | },
185 | hasPrevCmd: (inpSender) => {
186 | return !!previousCmds.find(n => n.sender == inpSender)
187 | },
188 | delPrevCmd: (inpSender) => {
189 | previousCmds = previousCmds.filter(({ sender }) => sender !== inpSender)
190 | }
191 | }
192 |
193 | //Gobal declaration
194 | const initGlobalVariable = () => {
195 | global.LOCAL_DATE_OPTIONS = {
196 | weekday: 'long',
197 | year: 'numeric',
198 | month: 'long',
199 | day: 'numeric',
200 | timeZoneName: 'short',
201 | hour: 'numeric',
202 | minute: 'numeric',
203 | }
204 | global.q3 = '```'
205 | global.readMore = `\u00AD`.repeat(1500) //it print 1500 characters so that makes whatsapp add 'read more' button
206 | global.color = (text, color) => _color(text, color)
207 | global.isLolApiActive = false
208 | global.simi = 0
209 | }
210 |
211 | export {
212 | initGlobalVariable,
213 | createReadFileSync,
214 | unlinkIfExists,
215 | receivedLog,
216 | processTime,
217 | commandLog,
218 | isFiltered,
219 | webpToPng,
220 | addFilter,
221 | download,
222 | formatin,
223 | inArray,
224 | lolApi,
225 | sleep,
226 | isUrl,
227 | prev,
228 | last,
229 | }
230 |
--------------------------------------------------------------------------------
/utils/options.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: SeroBot Team
3 | * @ Create Time: 2021-05-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified time: 2021-07-09 13:26:43
6 | * @ Description: options provided from owa issue (https://github.com/open-wa/wa-automate-nodejs/issues/563#issuecomment-647030529)
7 | */
8 |
9 | const chromeArgs = [
10 | '--disable-2d-canvas-clip-aa',
11 | '--disable-2d-canvas-image-chromium',
12 | '--disable-3d-apis',
13 | '--disable-accelerated-2d-canvas',
14 | '--disable-accelerated-jpeg-decoding',
15 | '--disable-accelerated-mjpeg-decode',
16 | '--disable-accelerated-video-decode',
17 | '--disable-app-list-dismiss-on-blur',
18 | '--disable-audio-output',
19 | '--disable-background-timer-throttling',
20 | '--disable-backgrounding-occluded-windows',
21 | '--disable-breakpad',
22 | '--disable-canvas-aa',
23 | '--disable-client-side-phishing-detection',
24 | '--disable-component-extensions-with-background-pages',
25 | '--disable-composited-antialiasing',
26 | '--disable-default-apps',
27 | '--disable-dev-shm-usage',
28 | '--disable-extensions',
29 | '--disable-features=TranslateUI,BlinkGenPropertyTrees',
30 | '--disable-field-trial-config',
31 | '--disable-fine-grained-time-zone-detection',
32 | '--disable-geolocation',
33 | '--disable-gl-extensions',
34 | '--disable-gpu',
35 | '--disable-gpu-early-init',
36 | '--disable-gpu-sandbox',
37 | '--disable-gpu-watchdog',
38 | '--disable-histogram-customizer',
39 | '--disable-in-process-stack-traces',
40 | '--disable-infobars',
41 | '--disable-ipc-flooding-protection',
42 | '--disable-notifications',
43 | '--disable-renderer-backgrounding',
44 | '--disable-session-crashed-bubble',
45 | '--disable-setuid-sandbox',
46 | '--disable-site-isolation-trials',
47 | '--disable-software-rasterizer',
48 | '--disable-sync',
49 | '--disable-threaded-animation',
50 | '--disable-threaded-scrolling',
51 | '--disable-translate',
52 | '--disable-webgl',
53 | '--disable-webgl2',
54 | '--enable-features=NetworkService',
55 | '--force-color-profile=srgb',
56 | '--hide-scrollbars',
57 | '--ignore-certifcate-errors',
58 | '--ignore-certifcate-errors-spki-list',
59 | '--ignore-certificate-errors',
60 | '--ignore-certificate-errors-spki-list',
61 | '--ignore-gpu-blacklist',
62 | '--ignore-ssl-errors',
63 | '--log-level=3',
64 | '--metrics-recording-only',
65 | '--mute-audio',
66 | '--no-crash-upload',
67 | '--no-default-browser-check',
68 | '--no-experiments',
69 | '--no-first-run',
70 | '--no-sandbox',
71 | '--no-zygote',
72 | '--renderer-process-limit=1',
73 | '--safebrowsing-disable-auto-update',
74 | '--silent-debugger-extension-api',
75 | '--single-process',
76 | '--unhandled-rejections=strict',
77 | '--window-position=0,0',
78 | '--aggressive-cache-discard',
79 | '--disable-cache',
80 | '--disable-application-cache',
81 | '--disable-offline-load-stale-cache',
82 | '--disk-cache-size=0'
83 | ]
84 |
85 | /**
86 | * Get Client Options
87 | * @param {Function} start function
88 | * @param {Boolean} headless
89 | */
90 | export default (headless, start) => {
91 | return {
92 | sessionId: 'session',
93 | headless: headless,
94 | useChrome: true,
95 | qrTimeout: 0,
96 | authTimeout: 0,
97 | restartOnCrash: start,
98 | cacheEnabled: false,
99 | killProcessOnBrowserClose: true,
100 | throwErrorOnTosBlock: false,
101 | chromiumArgs: chromeArgs
102 | }
103 | }
--------------------------------------------------------------------------------
/utils/resizeImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @ Author: YogaSakti
3 | * @ Create Time: 2021-05-31 22:33:11
4 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
5 | * @ Modified by: Danang Dwiyoga A (https://github.com/dngda/)
6 | * @ Modified time: 2021-06-28 19:48:08
7 | */
8 |
9 | import sharp from 'sharp'
10 | import fileType from 'file-type'
11 | const { fromBuffer } = fileType
12 |
13 | /**
14 | * Resize image to buffer or base64
15 | * @param {Buffer} bufferdata
16 | * @param {Boolean} encode
17 | * @param {String} mimType
18 | */
19 | // eslint-disable-next-line no-async-promise-executor
20 | const resizeImage = (buff, encode) => new Promise(async (resolve, reject) => {
21 | console.log(color('[LOGS]', 'grey'), 'Resizeing image...')
22 | const { mime } = await fromBuffer(buff)
23 | sharp(buff, { failOnError: false })
24 | .resize(512, 512)
25 | .toBuffer()
26 | .then(resizedImageBuffer => {
27 | if (!encode) return resolve(resizedImageBuffer)
28 | console.log(color('[LOGS]', 'grey'), 'Create base64 from resizedImageBuffer...')
29 | const resizedImageData = resizedImageBuffer.toString('base64')
30 | const resizedBase64 = `data:${mime};base64,${resizedImageData}`
31 | resolve(resizedBase64)
32 | })
33 | .catch(error => reject(error))
34 | })
35 |
36 | export default resizeImage
--------------------------------------------------------------------------------