├── .gitignore ├── config.json ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── package.json ├── LICENSE ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | savedUsers.json 2 | .directory 3 | node_modules 4 | .vscode/ -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "token": "BOT TOKEN", 3 | "maxInactivity": 86400000, 4 | "warnDelay": 43200000, 5 | "warnMessagesChannel": "CHANNEL ID", 6 | "testing": false 7 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "discord-inactive-user-kick", 3 | "version": "1.0.0", 4 | "description": "Automatically kicks a user if they haven't sent any messages for a specific time.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/Ishidres/discord-inactive-user-kick.git" 12 | }, 13 | "keywords": [ 14 | "Discord", 15 | "Bot", 16 | "Auto", 17 | "Kick", 18 | "User" 19 | ], 20 | "author": "Ishidres (www.ishidres.eu)", 21 | "license": "SEE LICENSE IN LICENSE", 22 | "bugs": { 23 | "url": "https://github.com/Ishidres/discord-inactive-user-kick/issues" 24 | }, 25 | "homepage": "https://github.com/Ishidres/discord-inactive-user-kick#readme", 26 | "dependencies": { 27 | "discord.js": "11.6.4" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ishidres (www.ishidres.eu) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Discord Inactive User Kick 2 | A simple Discord bot to automatically kick inactive server members created for [this](https://www.reddit.com/r/discordapp/comments/emgcn9/bot_for_kicking/) reddit post. 3 | 4 | ## Setup 5 | - install [Node.js](https://nodejs.org/en/) 6 | - install [discord.js@11.6.4](https://www.npmjs.com/package/discord.js/v/11.6.4) using `npm i discord.js@11.6.4` 7 | - create a new Discord bot [here](https://discordapp.com/developers/applications/) 8 | - add the bot's token to `config.json` and adjuste the configuration 9 | - run the bot by using `nohup node index.js &` or any other command you prefer 10 | 11 | Note: The bot uses JSON as a "database" which is not recommended for very large Discord servers with lots of members. In that case, please use MySQL. Servers with under 100K users can ignore this warning. 12 | 13 | Feel free to improve the bot using [pull requests](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/about-pull-requests)! 14 | 15 | ### Unsure? 16 | You can set `testing` to `true` in `config.json` to only simulate kicks without actually kicking a user to test it first. 17 | 18 | ### Questions 19 | You can ask me, the bot's developer, for help if you need it. Use my [website](https://ishidres.eu) or the badges below to contact me: 20 | 21 | [![Twitter](https://img.shields.io/twitter/url?label=Tweet%20me&style=social&url=https%3A%2F%2Ftwitter.com%2FIshidres)](https://twitter.com/Ishidres) 22 | [![Patreon](https://img.shields.io/badge/dynamic/json?url=https://www.patreon.com/api/campaigns/658859&label=Patreon&query=data.attributes.patron_count&suffix=%20patrons&color=f86754)](https://patreon.com/Ishidres) 23 | [![GitHub followers](https://img.shields.io/github/followers/Ishidres?style=social)](https://github.com/Ishidres) 24 | 25 | ### Contributing 26 | Thanks for using this repository! If you appreciate it or want to support its development, feel free to contribute by: 27 | - 👐 submitting [pull requests](https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/about-pull-requests) with improvements 28 | - ⭐️ starring the project 29 | - ➕ following [Ishidres](https://github.com/Ishidres) 30 | 31 | ### License 32 | This project is licensed under the [MIT License](https://choosealicense.com/licenses/mit/). For more information please have a look at the LICENSE file. -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const Discord = require('discord.js'); 2 | const client = new Discord.Client({ fetchAllMembers: true }); 3 | 4 | const fs = require("fs"); 5 | const config = require("./config.json"); 6 | const package = require("./package.json"); 7 | 8 | var saved_users = {}; 9 | 10 | // import savedUsers.json if it exists already 11 | if (fs.existsSync(__dirname + "/savedUsers.json")) 12 | saved_users = JSON.parse(fs.readFileSync("./savedUsers.json", "utf8")); 13 | 14 | client.on('ready', () => { 15 | console.log(new Date() + ": Logged in as " + client.user.tag); 16 | 17 | if (client.guilds.array().length > 1) { 18 | console.log("WARNING: The bot has been added to " + client.guilds.array().length + " servers but should only be used on one server at once and will now shutdown. Please remove the bot from all servers but one and restart it!"); 19 | process.exit(); 20 | } 21 | 22 | client.user.setPresence({ activity: { name: "by Ishidres#5758" }, status: 'online' }) 23 | }); 24 | 25 | client.on('message', message => { 26 | // Don't kick bots 27 | if (message.author.bot) return; 28 | 29 | // reply when receiving !help in direct message 30 | if (message.channel.type === "dm") { 31 | if (!!message.content) { 32 | if (message.content.toLowerCase().startsWith("!help")) 33 | message.reply("This bot doesn't offer any commands and has to be set up manually." 34 | + "\nPlease refer to " + package.homepage + " for more information."); 35 | } 36 | 37 | return; 38 | } 39 | 40 | if (!saved_users[message.author.id]) 41 | saved_users[message.author.id] = {}; 42 | 43 | saved_users[message.author.id].lastMessage = new Date().getTime(); 44 | saved_users[message.author.id].guild = message.guild.id; 45 | console.log(new Date() + ": Message received by " + message.author.tag); 46 | 47 | // Save the data 48 | fs.writeFileSync("./savedUsers.json", JSON.stringify(saved_users)); 49 | }); 50 | 51 | // checking for users to kick every 10 minutes (600 000 ms) 52 | setInterval(function () { 53 | let now = new Date().getTime(); 54 | let actions = 0; 55 | let all_users = client.users.array(); 56 | 57 | // Save all users 58 | for (y=0; y= 5) 76 | return; 77 | 78 | let diff = now - saved_users[i].lastMessage; 79 | let user = client.users.get(i); 80 | let channel = client.channels.get(config.warnMessagesChannel); 81 | 82 | if (!user) { 83 | user = "UserIsOffline#0000"; 84 | } else { 85 | user = user.tag; 86 | } 87 | 88 | if (diff >= config.warnDelay && saved_users[i].warned !== true) { 89 | console.log(new Date() + ": User " + i + " will be kicked in " + config.warnDelay + " ms."); 90 | 91 | if (!!channel) 92 | channel.send(":warning: User " + user + "<@" + i + ">" + " (ID: " + i + ") will be kicked in " + (config.warnDelay / 60 / 60 / 1000) + " hours."); 93 | 94 | saved_users[i].warned = true; 95 | actions++; 96 | } 97 | 98 | if (diff >= config.maxInactivity) { 99 | console.log(new Date() + ": Kicking User " + i + " due to inactivity."); 100 | var guild = client.guilds.get(saved_users[i].guild); 101 | 102 | // Don't really kick users if testing is enabled 103 | if (config.testing !== true) { 104 | guild.fetchMember(i).then(member => { 105 | member.kick("Kicked due to inactivity."); 106 | 107 | if (!!channel) 108 | channel.send("🔨 " + member.user.tag + " has been kicked due to inactivity."); 109 | }); 110 | } 111 | 112 | actions++; 113 | delete saved_users[i]; 114 | fs.writeFileSync("./savedUsers.json", JSON.stringify(saved_users)); 115 | } 116 | }); 117 | }, 60*1000); 118 | 119 | client.login(config.token); --------------------------------------------------------------------------------