Initial commit
This commit is contained in:
commit
fafaef850d
10 files changed
+1979
No files matched your search
@@ -0,0 +1,6 @@
|
|||||||
|
node_modules/
|
||||||
|
.env
|
||||||
|
.autoscale_bak/
|
||||||
|
.DS_Store
|
||||||
|
admin-users.json
|
||||||
|
user-mappings.json
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# Autoscale Bot
|
||||||
|
|
||||||
|
A self‑hosted Discord bot for managing a Headscale instance.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- Create, delete and manage Headscale users
|
||||||
|
- Link Discord accounts to Headscale users
|
||||||
|
- Register and rename nodes
|
||||||
|
- Ticketing system for support
|
||||||
|
- **Auto‑Updater**: Checks the GitHub repository for new releases, notifies the bot owner, and offers an in‑Discord update prompt.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
```bash
|
||||||
|
# Clone the repository
|
||||||
|
git clone https://github.com/jadonkortislolz-wq/autoscale.git
|
||||||
|
cd autoscale
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a `.env` file (do **not** commit it) with the required variables:
|
||||||
|
```
|
||||||
|
BOT_TOKEN=your_discord_bot_token
|
||||||
|
HEADSCALE_URL=https://your-headscale-url
|
||||||
|
HEADSCALE_CONTAINER=headscale
|
||||||
|
BOT_OWNER_ID=your_discord_user_id
|
||||||
|
# optional tickets config
|
||||||
|
TICKET_CATEGORY_ID=your_category_id
|
||||||
|
TICKET_SUPPORT_ROLE_ID=your_support_role_id
|
||||||
|
```
|
||||||
|
|
||||||
|
Start the bot (PM2 recommended):
|
||||||
|
```bash
|
||||||
|
npm start # or pm2 start ecosystem.config.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
All commands are prefixed with `!hs` or `!headscale`.
|
||||||
|
- `!hs create <username>` – Create a Headscale user
|
||||||
|
- `!hs discord <username>` – Link your Discord account to a Headscale user
|
||||||
|
- `!hs link <nodekey>` – Register a device
|
||||||
|
- `!hs register` – Get the Tailscale registration command
|
||||||
|
- `!hs list` – List all nodes and IPs
|
||||||
|
- `!hs rename <id> <new_name>` – Rename your node
|
||||||
|
- `!hs info` – Bot information
|
||||||
|
- Ticket commands: `!hs ticket panel`, `!hs ticket close`
|
||||||
|
- Admin commands: `!hs restart`, `!hs addadmin @user`, etc.
|
||||||
|
- `!hs update` – Check for a new version and update the bot
|
||||||
|
|
||||||
|
## Auto‑Updater
|
||||||
|
The bot automatically checks the GitHub repository for new releases every hour.
|
||||||
|
1. If a newer version is found, the bot owner receives a DM:
|
||||||
|
> "A new version **vX.Y.Z** is available. Run `!hs update` to apply it."
|
||||||
|
2. Running `!hs update` pulls the latest code, installs dependencies, and restarts the bot.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
Feel free to open issues or submit pull requests. Ensure you do not commit any secrets.
|
||||||
|
|
||||||
|
## License
|
||||||
|
ISC
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# Usage Guide for Autoscale Bot
|
||||||
|
|
||||||
|
## Command Prefixes
|
||||||
|
The bot listens for the following prefixes:
|
||||||
|
- `!hs`
|
||||||
|
- `!headscale`
|
||||||
|
|
||||||
|
## User Commands
|
||||||
|
| Command | Description |
|
||||||
|
| ------- | ----------- |
|
||||||
|
| `!hs create <username>` | Create a Headscale user |
|
||||||
|
| `!hs discord <username>` | Link your Discord account to a Headscale user |
|
||||||
|
| `!hs link <nodekey>` | Register a device |
|
||||||
|
| `!hs register` | Get the Tailscale registration command |
|
||||||
|
| `!hs list` | List all nodes and their IPs |
|
||||||
|
| `!hs rename <id> <new_name>` | Rename your node |
|
||||||
|
| `!hs info` | Show bot information |
|
||||||
|
| `!hs ticket panel` | Post the ticket panel (admin only) |
|
||||||
|
| `!hs ticket close` | Close a ticket (admin/support only) |
|
||||||
|
| `!hs restart` | Restart the bot (admin only) |
|
||||||
|
| `!hs update` | Check for a new version and update the bot |
|
||||||
|
|
||||||
|
## Admin Commands
|
||||||
|
- `!hs addadmin @user` – Grant admin privileges (owner only)
|
||||||
|
- `!hs removeadmin @user` – Revoke admin privileges (owner only)
|
||||||
|
- `!hs listadmins` – List all admin users
|
||||||
|
- `!hs deleteuser <username>` – Delete a Headscale user
|
||||||
|
- `!hs removenode <id>` – Force‑remove a node
|
||||||
|
- `!hs preauth <username>` – Generate a pre‑auth key
|
||||||
|
|
||||||
|
## Auto‑Updater
|
||||||
|
The `!hs update` command triggers the auto‑updater. If a newer release is found on GitHub, the bot will:
|
||||||
|
1. Pull the latest code.
|
||||||
|
2. Install any new dependencies.
|
||||||
|
3. Restart itself.
|
||||||
|
|
||||||
|
Make sure the bot has write permissions to its directory.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
module.exports = {
|
||||||
|
apps : [{
|
||||||
|
name: 'autoscale-bot',
|
||||||
|
script: 'index.js',
|
||||||
|
instances: 1,
|
||||||
|
exec_mode: 'fork',
|
||||||
|
autorestart: true,
|
||||||
|
watch: false,
|
||||||
|
max_memory_restart: '1G',
|
||||||
|
restart_delay: 5000,
|
||||||
|
exp_backoff_restart_delay: 100,
|
||||||
|
env: {
|
||||||
|
NODE_ENV: 'production',
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
Generated
+299
@@ -0,0 +1,299 @@
|
|||||||
|
{
|
||||||
|
"name": "autoscale",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "autoscale",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"discord.js": "^14.25.1",
|
||||||
|
"dotenv": "^17.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/builders": {
|
||||||
|
"version": "1.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.13.1.tgz",
|
||||||
|
"integrity": "sha512-cOU0UDHc3lp/5nKByDxkmRiNZBpdp0kx55aarbiAfakfKJHlxv/yFW1zmIqCAmwH5CRlrH9iMFKJMpvW4DPB+w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@discordjs/formatters": "^0.6.2",
|
||||||
|
"@discordjs/util": "^1.2.0",
|
||||||
|
"@sapphire/shapeshift": "^4.0.0",
|
||||||
|
"discord-api-types": "^0.38.33",
|
||||||
|
"fast-deep-equal": "^3.1.3",
|
||||||
|
"ts-mixer": "^6.0.4",
|
||||||
|
"tslib": "^2.6.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.11.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/collection": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-SVb428OMd3WO1paV3rm6tSjM4wC+Kecaa1EUGX7vc6/fddvw/6lg90z4QtCqm21zvVe92vMMDt9+DkIvjXImQQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/formatters": {
|
||||||
|
"version": "0.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.6.2.tgz",
|
||||||
|
"integrity": "sha512-y4UPwWhH6vChKRkGdMB4odasUbHOUwy7KL+OVwF86PvT6QVOwElx+TiI1/6kcmcEe+g5YRXJFiXSXUdabqZOvQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"discord-api-types": "^0.38.33"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.11.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/rest": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-RDYrhmpB7mTvmCKcpj+pc5k7POKszS4E2O9TYc+U+Y4iaCP+r910QdO43qmpOja8LRr1RJ0b3U+CqVsnPqzf4w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@discordjs/collection": "^2.1.1",
|
||||||
|
"@discordjs/util": "^1.1.1",
|
||||||
|
"@sapphire/async-queue": "^1.5.3",
|
||||||
|
"@sapphire/snowflake": "^3.5.3",
|
||||||
|
"@vladfrangu/async_event_emitter": "^2.4.6",
|
||||||
|
"discord-api-types": "^0.38.16",
|
||||||
|
"magic-bytes.js": "^1.10.0",
|
||||||
|
"tslib": "^2.6.3",
|
||||||
|
"undici": "6.21.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/rest/node_modules/@discordjs/collection": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/util": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/util/-/util-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-3LKP7F2+atl9vJFhaBjn4nOaSWahZ/yWjOvA4e5pnXkt2qyXRCHLxoBQy81GFtLGCq7K9lPm9R517M1U+/90Qg==",
|
||||||
|
"dependencies": {
|
||||||
|
"discord-api-types": "^0.38.33"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/ws": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@discordjs/collection": "^2.1.0",
|
||||||
|
"@discordjs/rest": "^2.5.1",
|
||||||
|
"@discordjs/util": "^1.1.0",
|
||||||
|
"@sapphire/async-queue": "^1.5.2",
|
||||||
|
"@types/ws": "^8.5.10",
|
||||||
|
"@vladfrangu/async_event_emitter": "^2.2.4",
|
||||||
|
"discord-api-types": "^0.38.1",
|
||||||
|
"tslib": "^2.6.2",
|
||||||
|
"ws": "^8.17.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.11.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/ws/node_modules/@discordjs/collection": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sapphire/async-queue": {
|
||||||
|
"version": "1.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.5.tgz",
|
||||||
|
"integrity": "sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=v14.0.0",
|
||||||
|
"npm": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sapphire/shapeshift": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-d9dUmWVA7MMiKobL3VpLF8P2aeanRTu6ypG2OIaEv/ZHH/SUQ2iHOVyi5wAPjQ+HmnMuL0whK9ez8I/raWbtIg==",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "^3.1.3",
|
||||||
|
"lodash": "^4.17.21"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=v16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sapphire/snowflake": {
|
||||||
|
"version": "3.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.5.3.tgz",
|
||||||
|
"integrity": "sha512-jjmJywLAFoWeBi1W7994zZyiNWPIiqRRNAmSERxyg93xRGzNYvGjlZ0gR6x0F4gPRi2+0O6S71kOZYyr3cxaIQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=v14.0.0",
|
||||||
|
"npm": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "25.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz",
|
||||||
|
"integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~7.18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/ws": {
|
||||||
|
"version": "8.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||||
|
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vladfrangu/async_event_emitter": {
|
||||||
|
"version": "2.4.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vladfrangu/async_event_emitter/-/async_event_emitter-2.4.7.tgz",
|
||||||
|
"integrity": "sha512-Xfe6rpCTxSxfbswi/W/Pz7zp1WWSNn4A0eW4mLkQUewCrXXtMj31lCg+iQyTkh/CkusZSq9eDflu7tjEDXUY6g==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=v14.0.0",
|
||||||
|
"npm": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/discord-api-types": {
|
||||||
|
"version": "0.38.42",
|
||||||
|
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.38.42.tgz",
|
||||||
|
"integrity": "sha512-qs1kya7S84r5RR8m9kgttywGrmmoHaRifU1askAoi+wkoSefLpZP6aGXusjNw5b0jD3zOg3LTwUa3Tf2iHIceQ=="
|
||||||
|
},
|
||||||
|
"node_modules/discord.js": {
|
||||||
|
"version": "14.25.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.25.1.tgz",
|
||||||
|
"integrity": "sha512-2l0gsPOLPs5t6GFZfQZKnL1OJNYFcuC/ETWsW4VtKVD/tg4ICa9x+jb9bkPffkMdRpRpuUaO/fKkHCBeiCKh8g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@discordjs/builders": "^1.13.0",
|
||||||
|
"@discordjs/collection": "1.5.3",
|
||||||
|
"@discordjs/formatters": "^0.6.2",
|
||||||
|
"@discordjs/rest": "^2.6.0",
|
||||||
|
"@discordjs/util": "^1.2.0",
|
||||||
|
"@discordjs/ws": "^1.2.3",
|
||||||
|
"@sapphire/snowflake": "3.5.3",
|
||||||
|
"discord-api-types": "^0.38.33",
|
||||||
|
"fast-deep-equal": "3.1.3",
|
||||||
|
"lodash.snakecase": "4.1.1",
|
||||||
|
"magic-bytes.js": "^1.10.0",
|
||||||
|
"tslib": "^2.6.3",
|
||||||
|
"undici": "6.21.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/discordjs/discord.js?sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dotenv": {
|
||||||
|
"version": "17.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
|
||||||
|
"integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://dotenvx.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fast-deep-equal": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||||
|
},
|
||||||
|
"node_modules/lodash": {
|
||||||
|
"version": "4.17.23",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||||
|
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="
|
||||||
|
},
|
||||||
|
"node_modules/lodash.snakecase": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
|
||||||
|
},
|
||||||
|
"node_modules/magic-bytes.js": {
|
||||||
|
"version": "1.13.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.13.0.tgz",
|
||||||
|
"integrity": "sha512-afO2mnxW7GDTXMm5/AoN1WuOcdoKhtgXjIvHmobqTD1grNplhGdv3PFOyjCVmrnOZBIT/gD/koDKpYG+0mvHcg=="
|
||||||
|
},
|
||||||
|
"node_modules/ts-mixer": {
|
||||||
|
"version": "6.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
|
||||||
|
"integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="
|
||||||
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
|
||||||
|
},
|
||||||
|
"node_modules/undici": {
|
||||||
|
"version": "6.21.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz",
|
||||||
|
"integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undici-types": {
|
||||||
|
"version": "7.18.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
||||||
|
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="
|
||||||
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
|
||||||
|
"integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": ">=5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "autoscale",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": "https://github.com/your-github-username/autoscale",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node index.js",
|
||||||
|
"update": "node updater.js",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": "^3.3.2",
|
||||||
|
"discord.js": "^14.25.1",
|
||||||
|
"dotenv": "^17.3.1"
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"ticketCounter": 0
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
// updater.js - Auto-updater for Autoscale Bot
|
||||||
|
// Checks the GitHub repository for a newer release and updates the bot.
|
||||||
|
// Requires node-fetch (added to dependencies).
|
||||||
|
|
||||||
|
const fetch = require('node-fetch');
|
||||||
|
const { execSync } = require('child_process');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
// Configuration - replace with actual repo owner/name if different.
|
||||||
|
const REPO = 'your-github-username/autoscale';
|
||||||
|
const GITHUB_API = `https://api.github.com/repos/${REPO}/releases/latest`;
|
||||||
|
|
||||||
|
function getCurrentVersion() {
|
||||||
|
try {
|
||||||
|
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
||||||
|
return pkg.version;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to read package.json:', e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getLatestRelease() {
|
||||||
|
try {
|
||||||
|
const resp = await fetch(GITHUB_API, { headers: { 'User-Agent': 'autoscale-updater' } });
|
||||||
|
if (!resp.ok) throw new Error(`GitHub API error ${resp.status}`);
|
||||||
|
const data = await resp.json();
|
||||||
|
return { version: data.tag_name.replace(/^v/, ''), tarball_url: data.tarball_url };
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to fetch latest release:', e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runUpdate() {
|
||||||
|
const current = getCurrentVersion();
|
||||||
|
const latest = await getLatestRelease();
|
||||||
|
if (!current || !latest) return;
|
||||||
|
|
||||||
|
if (current === latest.version) {
|
||||||
|
console.log(`✅ Already up‑to‑date (v${current}).`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`🔄 Updating from v${current} to v${latest.version}…`);
|
||||||
|
try {
|
||||||
|
// Pull latest code from git (assumes the repo is a git clone)
|
||||||
|
execSync('git fetch --all', { stdio: 'inherit' });
|
||||||
|
execSync(`git checkout v${latest.version}`, { stdio: 'inherit' });
|
||||||
|
// Install any new dependencies
|
||||||
|
execSync('npm install', { stdio: 'inherit' });
|
||||||
|
console.log('✅ Update complete. Restart the bot (e.g., pm2 restart autoscale).');
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Update failed:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
runUpdate();
|
||||||
|
}
|
||||||
Reference in new issue
Block a user