├── .env-example ├── .github └── workflows │ ├── deploy-dev.yml │ └── deploy-master.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── config.json ├── docker-entrypoint.sh ├── fMzdScKiYi.gif ├── index.js ├── package-lock.json ├── package.json ├── src ├── Commands │ ├── BotInfoCommand.js │ ├── GuidCommand.js │ ├── HelpCommand.js │ ├── SteamCommand.js │ └── UidCommand.js ├── Configs │ └── EnvironmentSelector.js ├── Constants │ ├── EnvironmentConstants.js │ ├── GameListConstants.js │ ├── GeneralConstants.js │ ├── HttpConstants.js │ └── TextConstants.js ├── Controllers │ ├── ApiController.js │ ├── HealthCheckController.js │ └── ServersController.js ├── Daos │ ├── ArmaDao.js │ ├── CommandsDao.js │ ├── DayzDao.js │ ├── GuidDao.js │ └── UidDao.js ├── Database │ ├── DbConnection.js │ └── Models │ │ ├── GeneralStore.js │ │ ├── GuidStore.js │ │ ├── UidStore.js │ │ ├── discordinfo.js │ │ ├── setArmaServer.js │ │ └── setdayzserver.js ├── Helpers │ └── GenericFunctions.js ├── Middlewares │ └── LoggerMiddleware.js ├── Models │ └── Response │ │ ├── ErrorResponse.js │ │ ├── FormaterResponse.js │ │ ├── ObtainGuidResponse.js │ │ └── ObtainUidResponse.js ├── Routes │ └── ApiRouter.js ├── WebServer.js └── services │ ├── ApiService.js │ ├── MessageEventService.js │ └── ServersService.js └── swagger.json /.env-example: -------------------------------------------------------------------------------- 1 | TOKEN=YOUR-DISCORD-BOT-TOKEN-HERE 2 | STEAM_API=YOUR-STEAM-API-KEY-HERE 3 | DB_URI=YOUR-MONGO-DB-URI-HERE 4 | DBL_TOKEN=YOUR_DBL_TOKEN_HERE 5 | CLIENT_ID=YOUR_BOT_CLIENT_ID 6 | API_PORT=API_PORT_HERE -------------------------------------------------------------------------------- /.github/workflows/deploy-dev.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - develop 5 | 6 | name: deploy bot to master infraestructure 7 | 8 | jobs: 9 | deploy: 10 | name: Build and push image to registry 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - name: Set up QEMU 16 | uses: docker/setup-qemu-action@v1 17 | 18 | - name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v1 20 | 21 | - name: Login to Private Registry 22 | uses: docker/login-action@v1 23 | with: 24 | registry: ${{ secrets.REGISTRY_URL }} 25 | username: ${{ secrets.REGISTRY_USERNAME }} 26 | password: ${{ secrets.REGISTRY_TOKEN }} 27 | 28 | - name: build and push to registry 29 | uses: docker/build-push-action@v3 30 | with: 31 | push: true 32 | context: . 33 | file: ./Dockerfile 34 | build-args: APP=dev 35 | platforms: linux/arm/v7 36 | tags: ${{ secrets.REGISTRY_URL }}/steamid64toguid-bot-dev:v2.1.3 37 | -------------------------------------------------------------------------------- /.github/workflows/deploy-master.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | 6 | name: deploy bot to master infraestructure 7 | 8 | jobs: 9 | deploy: 10 | name: Build and push image to registry 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - name: Set up QEMU 16 | uses: docker/setup-qemu-action@v1 17 | 18 | - name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v1 20 | 21 | - name: Login to Private Registry 22 | uses: docker/login-action@v1 23 | with: 24 | registry: ${{ secrets.REGISTRY_URL }} 25 | username: ${{ secrets.REGISTRY_USERNAME }} 26 | password: ${{ secrets.REGISTRY_TOKEN }} 27 | 28 | - name: build and push to registry 29 | uses: docker/build-push-action@v3 30 | with: 31 | push: true 32 | context: . 33 | file: ./Dockerfile 34 | build-args: APP=prod 35 | platforms: linux/arm/v7 36 | tags: ${{ secrets.REGISTRY_URL }}/steamid64toguid-bot-prod:v2.1.3 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | Commands-bk 3 | dev.json 4 | .env 5 | .env.dev 6 | .env.local -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16-buster-slim 2 | 3 | ENV APP $APP 4 | ENV API_PORT $API_PORT 5 | ENV TOKEN $TOKEN 6 | ENV DBL_TOKEN $DBL_TOKEN 7 | ENV STEAM_API $STEAM_API 8 | ENV DB_URI $DB_URI 9 | ENV CLIENT_ID $CLIENT_ID 10 | 11 | WORKDIR /app 12 | COPY . /app/ 13 | RUN chmod +x /app/docker-entrypoint.sh 14 | ENTRYPOINT ["/app/docker-entrypoint.sh"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 siegmund0 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DayZ - Arma 3 Discord Bot Calculator SteamID64 to Battleye GUID or UID 2 | 3 |
4 |

5 | 6 | Id64ToGuid 7 | 8 |

9 | 10 |
11 | 12 | ## Readme 13 | [Support Discord](https://discord.gg/M3FvUq8) 14 | 15 | [Bot invitation link](https://discord.com/api/oauth2/authorize?client_id=706139732073250860&permissions=537394240&scope=bot) 16 | 17 | siegmund0's Github Stats 18 | 19 |
20 | 21 | --- 22 | 23 | ## Features 24 | - ⚡ You can convert steamid64 to Guid or UID very easily and quickly (Battleye GUID or Bohemia Interactive UID). 25 | - 🌱 It has a command that displays a complete list of all bot commands 🤣 26 | 27 | - 🔭 Commands: 28 | 29 |
30 |

31 | 32 |

33 |
34 | 35 |
36 | 37 | ## Prerequisites 38 | - Have Node.js installed 39 | - It is necessary to have a MongoDb database. 40 | 41 | > **Note:** If **You Want** can join the support discord. 42 | 43 | --- 44 | 45 | ### Satisfactory GUID Convertion 46 |

47 | 48 |

49 | 50 | ### Satisfactory UID Convertion 51 |

52 | 53 |

54 | 55 | #### Steam id Finder 56 |

57 | 58 |

59 | 60 | --- 61 | 62 | ### YOU NEED MONGODB AND NODE.JS 63 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": { 3 | "active": true 4 | }, 5 | "api": { 6 | "active": true 7 | } 8 | } -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd /app 3 | npm install; 4 | npm run start:${APP}; -------------------------------------------------------------------------------- /fMzdScKiYi.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ignaciochemes/SteamID64ToGUID-Discord-Bot/82313e8ddfa48338db6dbdeb697c35634bc2d85a/fMzdScKiYi.gif -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const fs = require('node:fs'); 2 | const path = require('node:path'); 3 | const { Client, GatewayIntentBits, REST, Collection, Routes, ActivityType } = require("discord.js"); 4 | const { getEnvironment } = require("./src/Configs/EnvironmentSelector"); 5 | const { DatabaseConnection } = require("./src/Database/DbConnection"); 6 | const { WebServer } = require('./src/WebServer'); 7 | const { default: AutoPoster } = require('topgg-autoposter'); 8 | const config = require('./config.json'); 9 | 10 | getEnvironment(); 11 | if (config.database.active === true) { 12 | DatabaseConnection.getInstance(); 13 | } 14 | if (config.api.active === true) { 15 | new WebServer().listen(); 16 | } 17 | 18 | const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages] }); 19 | client.commands = new Collection(); 20 | const commandsPath = path.join(__dirname, './src/Commands'); 21 | const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); 22 | const commands = []; 23 | 24 | for (const file of commandFiles) { 25 | const filePath = path.join(commandsPath, file); 26 | const command = require(filePath); 27 | client.commands.set(command.data.name, command); 28 | commands.push(command.data.toJSON()); 29 | } 30 | 31 | const rest = new REST({ version: '10' }).setToken(process.env.TOKEN); 32 | 33 | setInterval(async () => { 34 | if (process.env.STEAMID_ENV === 'production') { 35 | const ap = AutoPoster(process.env.DBL_TOKEN, client); 36 | ap.on('posted', () => { 37 | console.log('Server count posted!'); 38 | }) 39 | } 40 | }, 3600000); 41 | 42 | (async () => { 43 | try { 44 | console.log('Started refreshing application (/) commands.'); 45 | await rest.put( 46 | Routes.applicationCommands(process.env.CLIENT_ID), 47 | { body: commands }, 48 | ); 49 | console.log('Successfully reloaded application (/) commands.'); 50 | } catch (error) { 51 | console.error(error); 52 | } 53 | })(); 54 | 55 | client.on('ready', () => { 56 | console.log(`Logeado como ${client.user.tag}`); 57 | let actividades = ['Arma', 'Dayz'], i = 0; 58 | setInterval(() => { client.user.setActivity(`/help | ${actividades[i++ % actividades.length]}`, { type: ActivityType.Watching }) }, 30000); 59 | }); 60 | 61 | client.on('interactionCreate', async interaction => { 62 | if (!interaction.isChatInputCommand()) return; 63 | const command = client.commands.get(interaction.commandName); 64 | if (!command) return; 65 | 66 | try { 67 | await command.execute(interaction); 68 | } catch (error) { 69 | console.error(error); 70 | await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true }); 71 | } 72 | }); 73 | 74 | client.login(process.env.TOKEN); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oaki", 3 | "version": "2.1.3", 4 | "description": "oakiBot", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "start:dev:win": "SET STEAMID_ENV=development&&node index.js", 9 | "start:local:win": "SET STEAMID_ENV=local&&nodemon index.js", 10 | "start:prod": "STEAMID_ENV=production node index.js", 11 | "start:dev": "STEAMID_ENV=development nodemon index.js", 12 | "start:local": "STEAMID_ENV=local nodemon index.js" 13 | }, 14 | "keywords": [ 15 | "-" 16 | ], 17 | "author": "oaki", 18 | "license": "ISC", 19 | "dependencies": { 20 | "@top-gg/sdk": "^3.1.6", 21 | "axios": "^1.6.5", 22 | "body-parser": "^1.20.2", 23 | "discord.js": "^14.14.1", 24 | "dotenv": "^16.3.1", 25 | "express": "^4.18.2", 26 | "express-winston": "^4.2.0", 27 | "gamedig": "^4.3.1", 28 | "mongoose": "^8.0.4", 29 | "morgan": "^1.10.0", 30 | "nodemon": "^3.0.2", 31 | "os": "^0.1.2", 32 | "os-utils": "0.0.14", 33 | "ping": "^0.4.4", 34 | "steamapi": "^2.5.0", 35 | "swagger-ui-express": "^5.0.0", 36 | "topgg-autoposter": "^2.0.1", 37 | "winston": "^3.11.0" 38 | } 39 | } -------------------------------------------------------------------------------- /src/Commands/BotInfoCommand.js: -------------------------------------------------------------------------------- 1 | const OS = require('os'); 2 | const os = require('os'); 3 | const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); 4 | const { GeneralConstants } = require("../Constants/GeneralConstants"); 5 | const { GeneralDao } = require("../Daos/CommandsDao"); 6 | const { formatUptime } = require('../Helpers/GenericFunctions'); 7 | 8 | module.exports = { 9 | data: new SlashCommandBuilder() 10 | .setName("bot-info") 11 | .setDescription("Shows server info"), 12 | async execute(interaction) { 13 | let aggregate = await GeneralDao.generalStoreDao(interaction.commandName, interaction.user.id, GeneralConstants.COMANDOS); 14 | aggregate[0] ? aggregate = aggregate[0].Total : aggregate = 1; 15 | let embed = new EmbedBuilder(); 16 | embed.setTitle(`Bot Information`); 17 | embed.setColor(GeneralConstants.DEFAULT_COLOR); 18 | embed.addFields( 19 | { 20 | name: "General:", 21 | value: `Name: \`${interaction.client.user.username}\` \nID: \`${interaction.client.user.id}\` \nGuilds: \`${interaction.client.guilds.cache.size}\` \nUsers: \`${interaction.client.users.cache.size}\``, 22 | inline: true 23 | }, 24 | { 25 | name: "Developer:", 26 | value: `Name: \`${interaction.client.users.cache.get(GeneralConstants.DEVELOPER_ID).username}\` \nID: \`${GeneralConstants.DEVELOPER_ID}\``, 27 | inline: true 28 | }, 29 | { 30 | name: "System:", 31 | value: `Platform: \`${OS.platform()}\` \nCPU: \`${OS.cpus()[0].model}\` \nRAM: \`${Math.round(OS.totalmem() / 1024 / 1024)} MB\`` 32 | }, 33 | { 34 | name: "Process Usage:", 35 | value: `CPU: \`${Math.round(process.cpuUsage().system / 1024 / 1024)} %\` \nRAM: \`${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)} MB\``, 36 | inline: true 37 | }, 38 | { 39 | name: "System Free Resources:", 40 | value: `CPU: \`${Math.round(os.loadavg()[0] * 100)} %\` \nRAM: \`${Math.round(os.freemem() / 1024 / 1024)} MB\``, 41 | inline: true 42 | }, 43 | { 44 | name: "Node.js:", 45 | value: `Version: \`${process.version}\` \nArchitecture: \`${process.arch}\``, 46 | }, 47 | { 48 | name: "Statistics:", 49 | value: `Commands used: \`${aggregate}\``, 50 | inline: true 51 | }, 52 | { 53 | name: "Uptime:", 54 | value: `\`${formatUptime(os.uptime())}\``, 55 | inline: true 56 | } 57 | ); 58 | embed.setThumbnail(`${interaction.client.user.displayAvatarURL()}`); 59 | embed.setFooter({ text: GeneralConstants.DEFAULT_FOOTER }); 60 | await interaction.reply({ embeds: [embed] }); 61 | } 62 | } -------------------------------------------------------------------------------- /src/Commands/GuidCommand.js: -------------------------------------------------------------------------------- 1 | const { createHash } = require("crypto"); 2 | const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); 3 | const { GeneralConstants } = require("../Constants/GeneralConstants"); 4 | const { TextConstants } = require("../Constants/TextConstants"); 5 | const { GeneralDao } = require("../Daos/CommandsDao"); 6 | const { GuidDao } = require("../Daos/GuidDao"); 7 | 8 | module.exports = { 9 | data: new SlashCommandBuilder() 10 | .setName('guid') 11 | .setDescription('Convert SteamId64 to GUID') 12 | .addStringOption(option => 13 | option.setName('steamid64') 14 | .setDescription('Enter your SteamId64') 15 | .setRequired(true) 16 | ), 17 | async execute(interaction) { 18 | let aggregate = await GuidDao.agregate(); 19 | aggregate[0] ? aggregate = aggregate[0].Total : aggregate = 1; 20 | await GeneralDao.generalStoreDao(interaction.commandName, interaction.user.id, GeneralConstants.COMANDOS); 21 | const steamId64 = interaction.options.getString('steamid64'); 22 | if (!/^\d{17}$/.test(steamId64)) { 23 | return interaction.reply({ content: TextConstants.GUID_MENOR_ARGS, ephemeral: true }); 24 | }; 25 | let embed = new EmbedBuilder(); 26 | let guid; 27 | try { 28 | const buffer = Buffer.alloc(10); 29 | buffer.writeBigUInt64LE(BigInt(steamId64)); 30 | guid = createHash('md5').update(Buffer.concat([Buffer.from([0x42, 0x45]), buffer.subarray(0, 8)])).digest('hex'); 31 | await GeneralDao.guidStoreDao(guid, interaction.user.id, aggregate) 32 | embed.setDescription("<@" + interaction.user.id + ">" + " " + `Global GUID converted: \`${aggregate}\``); 33 | embed.addFields( 34 | { name: 'SteamId64', value: `\`${steamId64}\``, inline: true }, 35 | { name: 'GUID', value: `\`${guid}\``, inline: true } 36 | ); 37 | embed.setColor(GeneralConstants.DEFAULT_COLOR); 38 | embed.setFooter({ text: GeneralConstants.DEFAULT_FOOTER }); 39 | } catch (error) { 40 | embed.setTitle('Error converting'); 41 | embed.setDescription(`Are you sure you entered a correct number? \nExecute /steam and enter your Steam Link. Like this: \`/steam 765611....\` \nYou have to find your SteamId64 765611 .... and then, use it with the command \`/guid 765611.....\` to return the hash.`) 42 | embed.setColor("#A62019"); 43 | } finally { 44 | return interaction.reply({ embeds: [embed] }); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/Commands/HelpCommand.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); 2 | const { GeneralConstants } = require("../Constants/GeneralConstants"); 3 | const { GeneralDao } = require("../Daos/CommandsDao"); 4 | 5 | module.exports = { 6 | data: new SlashCommandBuilder() 7 | .setName("help") 8 | .setDescription("Shows all commands"), 9 | async execute(interaction) { 10 | let aggregate = await GeneralDao.generalStoreDao(interaction.commandName, interaction.user.id, GeneralConstants.COMANDOS); 11 | aggregate[0] ? aggregate = aggregate[0].Total : aggregate = 1; 12 | let embed = new EmbedBuilder(); 13 | const allCommands = interaction.client.commands.map(command => command.data.toJSON()); 14 | const commands = allCommands.map(command => { 15 | return { 16 | name: `\`/${command.name}\``, 17 | value: `Description: ${command.description} \nUsage: /${command.name}`, 18 | } 19 | }); 20 | embed.setTitle(`Commands`); 21 | embed.setDescription('For use a command, type / before the command name'); 22 | embed.setColor(GeneralConstants.DEFAULT_COLOR); 23 | embed.addFields(commands); 24 | embed.setFooter({ text: GeneralConstants.DEFAULT_FOOTER }); 25 | await interaction.reply({ embeds: [embed] }); 26 | } 27 | } -------------------------------------------------------------------------------- /src/Commands/SteamCommand.js: -------------------------------------------------------------------------------- 1 | const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); 2 | const SteamAPI = require("steamapi"); 3 | const { GeneralConstants } = require("../Constants/GeneralConstants"); 4 | const { GeneralDao } = require("../Daos/CommandsDao"); 5 | 6 | const steam = new SteamAPI(process.env.STEAM_API); 7 | let id64Resolve = []; 8 | 9 | module.exports = { 10 | data: new SlashCommandBuilder() 11 | .setName("steam") 12 | .setDescription("Convert Steam profile url to SteamId64") 13 | .addStringOption(option => 14 | option.setName("steamurl") 15 | .setDescription("Enter your Steam profile url") 16 | .setRequired(true) 17 | ), 18 | async execute(interaction) { 19 | await GeneralDao.generalStoreDao(interaction.commandName, interaction.user.id, GeneralConstants.COMANDOS); 20 | const pwd = interaction.options._hoistedOptions[0].value; 21 | let embed = new EmbedBuilder(); 22 | try { 23 | let resolve = await steam.resolve(pwd).then(id => { 24 | id64Resolve = id; 25 | if (id64Resolve.toString().length != 17) return interaction.reply('Something is wrong. Please try again.'); 26 | return id64Resolve; 27 | }); 28 | steam.getUserSummary(resolve).then(summary => { 29 | const { nickName, realName, countryCode } = _steamInfoCorrector(summary.nickname, summary.realName, summary.countryCode); 30 | if (summary.gameServerIP, summary.gameServerSteamID, summary.gameExtraInfo, summary.gameID === undefined) { 31 | embed.setTitle(`Steam Information`); 32 | embed.setColor(GeneralConstants.DEFAULT_COLOR); 33 | embed.addFields( 34 | { 35 | name: "General:", 36 | value: `Nickname: \`${nickName}\` \nReal Name: \`${realName}\` \nCountry Code: \`${countryCode}\``, 37 | inline: true 38 | }, 39 | { 40 | name: "Steam ID 64:", 41 | value: `Steam ID: \`${summary.steamID}\``, 42 | inline: true 43 | } 44 | ); 45 | embed.setThumbnail(`${summary.avatar.large}`); 46 | embed.setFooter({ text: GeneralConstants.DEFAULT_FOOTER }); 47 | return interaction.reply({ embeds: [embed] }); 48 | } else { 49 | embed.setTitle(`Steam Information`); 50 | embed.setColor(GeneralConstants.DEFAULT_COLOR); 51 | embed.addFields( 52 | { 53 | name: "General:", 54 | value: `Nickname: \`${nickName}\` \nReal Name: \`${realName}\` \nCountry Code: \`${countryCode}\``, 55 | inline: true 56 | }, 57 | { 58 | name: "Steam ID 64:", 59 | value: `Steam ID: \`${summary.steamID}\``, 60 | inline: true 61 | }, 62 | { 63 | name: "Game:", 64 | value: `\nGame Server IP: \`${summary.gameServerIP}\` \nGame Server Steam ID: \`${summary.gameServerSteamID}\` \nGame Extra Info: \`${summary.gameExtraInfo}\` \nGame ID: \`${summary.gameID}\``, 65 | inline: true 66 | } 67 | ); 68 | embed.setThumbnail(`${summary.avatar.large}`); 69 | embed.setFooter({ text: GeneralConstants.DEFAULT_FOOTER }); 70 | return interaction.reply({ embeds: [embed] }); 71 | } 72 | }); 73 | } catch (error) { 74 | embed.setTitle(`Steam Information`); 75 | embed.setColor(GeneralConstants.DEFAULT_COLOR); 76 | embed.setDescription(`Something is wrong. Please try again.`); 77 | embed.setFooter({ text: GeneralConstants.DEFAULT_FOOTER }); 78 | } 79 | } 80 | } 81 | 82 | const _steamInfoCorrector = (nickName, realName, countryCode) => { 83 | !nickName || nickName === null ? nickName = 'Not found' : nickName = nickName; 84 | !realName || realName === null ? realName = 'Not found' : realName = realName; 85 | !countryCode || countryCode === null ? countryCode = 'Not found' : countryCode = countryCode; 86 | return { nickName, realName, countryCode }; 87 | } -------------------------------------------------------------------------------- /src/Commands/UidCommand.js: -------------------------------------------------------------------------------- 1 | const { createHash } = require("crypto"); 2 | const { SlashCommandBuilder, EmbedBuilder } = require("discord.js"); 3 | const { GeneralConstants } = require("../Constants/GeneralConstants"); 4 | const { TextConstants } = require("../Constants/TextConstants"); 5 | const { GeneralDao } = require("../Daos/CommandsDao"); 6 | const { UidDao } = require("../Daos/UidDao"); 7 | 8 | module.exports = { 9 | data: new SlashCommandBuilder() 10 | .setName('uid') 11 | .setDescription('Convert SteamId64 to UID') 12 | .addStringOption(option => 13 | option.setName('steamid64') 14 | .setDescription('Enter your SteamId64') 15 | .setRequired(true) 16 | ), 17 | async execute(interaction) { 18 | let aggregate = await UidDao.agregate(); 19 | aggregate[0] ? aggregate = aggregate[0].Total : aggregate = 1; 20 | await GeneralDao.generalStoreDao(interaction.commandName, interaction.user.id, GeneralConstants.COMANDOS); 21 | const steamId64 = interaction.options.getString('steamid64'); 22 | if (!/^\d{17}$/.test(steamId64)) { 23 | return interaction.reply({ content: TextConstants.UID_MENOR_ARGS, ephemeral: true }); 24 | }; 25 | let embed = new EmbedBuilder(); 26 | try { 27 | let pwdToBase64 = createHash('sha256').update(steamId64).digest('base64'); 28 | let pwdReplace = pwdToBase64.replace(GeneralConstants.MAS_REGEX, GeneralConstants.GUION); 29 | let pwdFinally = pwdReplace.replace(GeneralConstants.BARRA_REGEX, GeneralConstants.GUION_BAJO); 30 | await GeneralDao.uidStoreDao(pwdFinally, interaction.user.id, aggregate); 31 | embed.setDescription("<@" + interaction.user.id + ">" + " " + `Global UIDS converted: \`${aggregate}\``); 32 | embed.addFields( 33 | { name: 'SteamId64', value: `\`${steamId64}\``, inline: true }, 34 | { name: '✅ Works UID', value: `\`${pwdFinally}\`` }, 35 | { name: '❌ Test UID', value: `\`${pwdToBase64}\`` } 36 | ); 37 | embed.setColor(GeneralConstants.DEFAULT_COLOR); 38 | embed.setFooter({ text: GeneralConstants.DEFAULT_FOOTER }); 39 | } catch (error) { 40 | console.log(error); 41 | embed.setTitle('Error converting'); 42 | embed.setDescription(`Are you sure you entered a correct number? \nExecute /steam and enter your Steam Link. Like this: \`/steam 765611....\` \nYou have to find your SteamId64 765611 .... and then, use it with the command \`/uid 765611.....\` to return the hash.`) 43 | embed.setColor("#A62019"); 44 | } finally { 45 | return interaction.reply({ embeds: [embed] }); 46 | } 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /src/Configs/EnvironmentSelector.js: -------------------------------------------------------------------------------- 1 | const dotenv = require('dotenv'); 2 | const path = require('path'); 3 | const { EnvironmentConstants } = require('../Constants/EnvironmentConstants'); 4 | 5 | const PROD = EnvironmentConstants.PROD; 6 | const DEV = EnvironmentConstants.DEV; 7 | const LOCAL = EnvironmentConstants.LOCAL; 8 | 9 | let envData = {}; 10 | 11 | const getEnvironment = () => { 12 | switch (process.env.STEAMID_ENV) { 13 | case PROD: 14 | envData = dotenv.config({ path: path.resolve(__dirname, '../../.env') }).parsed; 15 | console.log('Environment: Production'); 16 | break; 17 | case DEV: 18 | envData = dotenv.config({ path: path.resolve(__dirname, '../../.env.dev') }).parsed; 19 | console.log('Environment: Development'); 20 | break 21 | case LOCAL: 22 | envData = dotenv.config({ path: path.resolve(__dirname, '../../.env.local') }).parsed; 23 | console.log('Environment: Local'); 24 | break 25 | default: 26 | envData = dotenv.config({ path: path.resolve(__dirname, '../../.env') }).parsed; 27 | } 28 | } 29 | 30 | module.exports = { getEnvironment, envData } -------------------------------------------------------------------------------- /src/Constants/EnvironmentConstants.js: -------------------------------------------------------------------------------- 1 | class EnvironmentConstants { 2 | static PROD = 'production'; 3 | static LOCAL = 'local'; 4 | static DEV = 'development' 5 | } 6 | 7 | module.exports = { EnvironmentConstants }; -------------------------------------------------------------------------------- /src/Constants/GameListConstants.js: -------------------------------------------------------------------------------- 1 | const GameList = { 2 | games: { 3 | 'arma3': 'Arma 3', 4 | 'arma2': 'Arma 2', 5 | 'dayz': 'Dayz Standalone', 6 | 'dayzmod': 'Dayz Mod 2013', 7 | 'csgo': 'Counter-Strike: Global Offensive', 8 | 'cs16': 'Counter-Strike 1.6', 9 | 'fivem': 'FiveM', 10 | 'samp': 'San Andreas Multiplayer', 11 | 'mtasa': 'MTA San Andreas', 12 | 'mtavc': 'MTA Vice City', 13 | 'minecraft': 'Minecraft', 14 | 'minecraftpe': 'Minecraft: Pocket Edition', 15 | 'ps': 'Post Scriptum', 16 | 'przomboid': 'Project Zomboid', 17 | 'rust': 'Rust', 18 | 'rfactor': 'rFactor', 19 | 'squad': 'Squad', 20 | 'valheim': 'Valheim', 21 | '7d2d': '7 Days to Die', 22 | 'aoe2': 'Age of Empires 2', 23 | 'arkse': 'Ark Survival Evolved', 24 | 'assettocorsa': 'Assetto Corsa', 25 | 'conanexiles': 'Conan Exiles', 26 | 'garrysmod': 'Garry\'s Mod', 27 | 'hll': 'Hell Let Loose', 28 | 'insurgency': 'Insurgency', 29 | 'insurgencysandstorm': 'Insurgency: Sandstorm', 30 | 'killingfloor': 'Killing Floor', 31 | 'killingfloor2': 'Killing Floor 2', 32 | 'left4dead': 'Left 4 Dead', 33 | 'left4dead2': 'Left 4 Dead 2', 34 | 'openttd': 'OpenTTD', 35 | }, 36 | services: { 37 | 'teamspeak3': 'TeamSpeak 3', 38 | 'teamspeak2': 'TeamSpeak 2', 39 | 'ventrilo': 'Ventrilo', 40 | 'discord': 'Discord', 41 | } 42 | }; 43 | 44 | module.exports = { GameList }; -------------------------------------------------------------------------------- /src/Constants/GeneralConstants.js: -------------------------------------------------------------------------------- 1 | class GeneralConstants { 2 | static COMANDOS = 'comandos'; 3 | static MAS_REGEX = /\+/g; 4 | static GUION = '-'; 5 | static GUION_BAJO = '_'; 6 | static BARRA_REGEX = /\//g; 7 | static THUMBNAIL = 'https://i.imgur.com/mnSJzVk.jpg'; 8 | static DISPLAY_COLOR_1 = '#000000'; 9 | static DISPLAY_COLOR_2 = '#ffffff'; 10 | static DEFAULT_COLOR = '#F8C300'; 11 | static DEFAULT_FOOTER = '2024 © Id64ToGuid | Bohemia Interactive - Battleye | Develop by oaki'; 12 | static GENERAL_TIMEOUT = 60000; 13 | static BOT_INVITE_LINK = '\n https://discordapp.com/api/oauth2/authorize?client_id=706139732073250860&permissions=523328&scope=bot'; 14 | static GITHUB_LINK = '\n https://github.com/ignaciochemes/SteamID64ToGUID-Discord-Bot'; 15 | static SUPORT_DISCORD = '\n https://discord.gg/6YtgFUg'; 16 | static LOGS2_CHANNEL = '841775829066317844'; 17 | static LOGS_CHANNEL = '792023635203457025'; 18 | static DEVELOPER_ID = '257668549051547649'; 19 | } 20 | 21 | module.exports = { GeneralConstants } -------------------------------------------------------------------------------- /src/Constants/HttpConstants.js: -------------------------------------------------------------------------------- 1 | class HttpConstants { 2 | static OK = 200; 3 | static BAD_REQUEST = 400; 4 | static UNAUTHORIZED = 401; 5 | static NOT_FOUND = 404; 6 | static INTERNAL_SERVER_ERROR = 500; 7 | } 8 | 9 | module.exports = { HttpConstants }; -------------------------------------------------------------------------------- /src/Constants/TextConstants.js: -------------------------------------------------------------------------------- 1 | class TextConstants { 2 | static UID_NO_ARGS = `Insert account id64 | -uid | -uid 765611981... \nIf you dont have your steam id 64 number, please execute the following command\n\`-steam \`\nExample -steam https://steamcommunity.com/id/siegmundsensi/`; 3 | static UID_MENOR_ARGS = `The entered arguments are wrong or not complete. Please check the data. \nIf you have any questions, just enter the uid comman. | /uid | /uid 765611981... \nIf you dont have your steam id 64 number, please execute the following command\n\`/steam \`\nExample /steam https://steamcommunity.com/id/siegmundsensi/`; 4 | static GUID_NO_ARGS = 'Insert account id64 | /guid | /guid 765611981... \nIf you dont have your steam id 64 number, please execute the following command\n\`/steam \`\nExample /steam https://steamcommunity.com/id/siegmundsensi/'; 5 | static GUID_MENOR_ARGS = 'The entered arguments are wrong or not complete. Please check the data. \nIf you have any questions, just enter the /guid comman. | /guid | /guid 765611981... \nIf you dont have your steam id 64 number, please execute the following command\n\`/steam \`\nExample /steam https://steamcommunity.com/id/siegmundsensi/'; 6 | static SETPREFIX_NO_ARGS = 'You must provide a **new prefix**!'; 7 | static SETPREFIX_MAYOR_ARGS = 'Your new prefix must be under \`5\` characters!'; 8 | static SETDAYZ_NO_ARGS = 'You must provide your **Dayz Server IP**. Eg: \`-setdayzserver 0.0.0.0\` and press enter.'; 9 | static SETDAYZ_MAYOR_ARGS = 'Your new ip must be under \`15\` characters!'; 10 | static SETARMA_NO_ARGS = 'You must provide your **Arma 3 Server IP**. Eg: \`-setarma3server 0.0.0.0\` and press enter.'; 11 | static SETARMA_MAYOR_ARGS = 'Your new ip must be under \`15\` characters!'; 12 | static ID64_NO_ARGS = 'Insert account url | -steam '; 13 | static ARMA_NO_USER_IP = 'No ip related to your discord profile.id was found. Please enter the following command to configure one. \`-setarma3server\`.'; 14 | static DAYZ_NO_USER_IP = 'No ip related to your discord profile.id was found. Please enter the following command to configure one. \`-setdayzserver\`.'; 15 | 16 | static QUERY_PORT = 'Now I need you to put the QUERY port of the server to trace. Write the number and press ENTER \nThis message will be deleted in a minute.'; 17 | static NO_QUERY_PORT = 'You didnt enter the QUERY port. You have to start the operation again!'; 18 | static CANCEL = 'Operation canceled!'; 19 | static DB_SORT_ERROR = 'No se pudo sortear la base'; 20 | } 21 | 22 | module.exports = { TextConstants }; -------------------------------------------------------------------------------- /src/Controllers/ApiController.js: -------------------------------------------------------------------------------- 1 | const { FormaterResponse } = require("../Models/Response/FormaterResponse"); 2 | const { ApiService } = require("../services/ApiService"); 3 | 4 | class ApiController { 5 | 6 | static async guidController(req, res) { 7 | const response = await ApiService.obtainGuid(req); 8 | return res.json(new FormaterResponse(response)); 9 | } 10 | 11 | static uidController(req, res) { 12 | const response = ApiService.uidService(req); 13 | return res.json(new FormaterResponse(response)); 14 | } 15 | 16 | } 17 | 18 | module.exports = { ApiController }; -------------------------------------------------------------------------------- /src/Controllers/HealthCheckController.js: -------------------------------------------------------------------------------- 1 | const { FormaterResponse } = require("../Models/Response/FormaterResponse"); 2 | 3 | class HealthCheckController { 4 | 5 | static async healthCheck(req, res) { 6 | const response = { status: "OK", message: "Server is running" }; 7 | return res.json(new FormaterResponse(response)); 8 | } 9 | 10 | } 11 | 12 | module.exports = { HealthCheckController }; -------------------------------------------------------------------------------- /src/Controllers/ServersController.js: -------------------------------------------------------------------------------- 1 | const { FormaterResponse } = require("../Models/Response/FormaterResponse"); 2 | const { ServersService } = require("../services/ServersService"); 3 | 4 | class ServersController { 5 | 6 | static async getServerInfo(req, res) { 7 | const response = await ServersService.getServerInfo(req); 8 | return res.json(new FormaterResponse(response)); 9 | } 10 | 11 | static async getGamesList(req, res) { 12 | const response = await ServersService.getGamesList(); 13 | return res.json(new FormaterResponse(response)); 14 | } 15 | } 16 | 17 | module.exports = { ServersController }; -------------------------------------------------------------------------------- /src/Daos/ArmaDao.js: -------------------------------------------------------------------------------- 1 | const armaSchema = require('../database/models/setArmaServer'); 2 | 3 | class ArmaDao { 4 | 5 | static async save(message, ip, puerto) { 6 | const newData = new armaSchema({ 7 | Arma3Ip: ip, 8 | ArmaPort: puerto, 9 | GuildID: message.author.id, 10 | }) 11 | await newData.save(); 12 | }; 13 | 14 | static async setServer(message) { 15 | return await armaSchema.findOneAndRemove({ GuildID: message.author.id }); 16 | }; 17 | 18 | static async getServer(message) { 19 | const query = await armaSchema.findOne({ GuildID: message.author.id }); 20 | return query; 21 | }; 22 | } 23 | 24 | module.exports = { ArmaDao }; -------------------------------------------------------------------------------- /src/Daos/CommandsDao.js: -------------------------------------------------------------------------------- 1 | const uidStoreSchema = require('../Database/Models/UidStore'); 2 | const guidStoreSchema = require('../Database/Models/GuidStore'); 3 | const generalStoreSchema = require('../Database/Models/GeneralStore'); 4 | 5 | class GeneralDao { 6 | 7 | static async generalStoreDao(commandName, userId, commandType) { 8 | const newDataGeneral = new generalStoreSchema({ 9 | comando: commandName, 10 | user: userId, 11 | name: commandType 12 | }); 13 | await newDataGeneral.save(); 14 | const count = await generalStoreSchema.aggregate([{ $group: { _id: "$name", Total: { $sum: 1 } } }]); 15 | return count; 16 | }; 17 | 18 | static async uidStoreDao(uid, userId, aggregate) { 19 | const newData = new uidStoreSchema({ 20 | uid: uid, 21 | user: userId, 22 | name: "uid", 23 | numero: aggregate, 24 | }); 25 | await newData.save(); 26 | } 27 | 28 | static async guidStoreDao(guid, userId, aggregate) { 29 | const newData = new guidStoreSchema({ 30 | guid: guid, 31 | user: userId, 32 | name: "guid", 33 | numero: aggregate, 34 | }); 35 | await newData.save(); 36 | } 37 | } 38 | 39 | module.exports = { GeneralDao }; -------------------------------------------------------------------------------- /src/Daos/DayzDao.js: -------------------------------------------------------------------------------- 1 | const dayzSchema = require('../Database/Models/setDayzServer'); 2 | 3 | class DayzDao { 4 | 5 | static async save(message, ip, puerto) { 6 | const newData = new dayzSchema({ 7 | DayzIp: ip, 8 | DayzPort: puerto, 9 | GuildID: message.author.id, 10 | }) 11 | await newData.save(); 12 | }; 13 | 14 | static async setServer(message) { 15 | await dayzSchema.findOneAndRemove({ GuildID: message.author.id }); 16 | }; 17 | 18 | static async getServer(message) { 19 | const query = await dayzSchema.findOne({ GuildID: message.author.id }); 20 | return query; 21 | } 22 | } 23 | 24 | module.exports = { DayzDao }; -------------------------------------------------------------------------------- /src/Daos/GuidDao.js: -------------------------------------------------------------------------------- 1 | const guidStoreSchema = require("../Database/Models/GuidStore"); 2 | 3 | class GuidDao { 4 | static async agregate() { 5 | return await guidStoreSchema.aggregate([ 6 | { 7 | $group: { 8 | _id: "$name", 9 | Total: { $sum: 1 } 10 | } 11 | } 12 | ]) 13 | } 14 | } 15 | 16 | module.exports = { GuidDao }; -------------------------------------------------------------------------------- /src/Daos/UidDao.js: -------------------------------------------------------------------------------- 1 | const uidStoreSchema = require("../Database/Models/UidStore"); 2 | 3 | class UidDao { 4 | 5 | static async agregate() { 6 | return await uidStoreSchema.aggregate([ 7 | { 8 | $group: { 9 | _id: "$name", 10 | Total: { $sum: 1 } 11 | } 12 | } 13 | ]) 14 | } 15 | } 16 | 17 | module.exports = { UidDao }; -------------------------------------------------------------------------------- /src/Database/DbConnection.js: -------------------------------------------------------------------------------- 1 | const { connect } = require('mongoose'); 2 | 3 | class DatabaseConnection { 4 | static _instancia; 5 | constructor() { 6 | this.dbConnection(); 7 | } 8 | 9 | static getInstance() { 10 | if (DatabaseConnection._instancia) throw new Error('Ya existe una instancia de DatabaseConnection'); 11 | DatabaseConnection._instancia = new DatabaseConnection(); 12 | return DatabaseConnection._instancia; 13 | } 14 | 15 | async dbConnection() { 16 | await connect(`${process.env.DB_URI}`) 17 | .then(() => { console.log('Base de datos conectada!') }) 18 | .catch((e) => { console.log('Error al conectar con la base de datos!', e) }) 19 | }; 20 | } 21 | 22 | module.exports = { DatabaseConnection }; -------------------------------------------------------------------------------- /src/Database/Models/GeneralStore.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose'); 2 | 3 | const generalStoreSchema = new Schema({ 4 | comando: { type: String }, 5 | user: { type: String }, 6 | name: { type: String }, 7 | }); 8 | 9 | module.exports = model('generalAlmacenamiento', generalStoreSchema); -------------------------------------------------------------------------------- /src/Database/Models/GuidStore.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose'); 2 | 3 | const guidStoreSchema = new Schema({ 4 | guid: { type: String }, 5 | user: { type: String }, 6 | name: { type: String }, 7 | numero: { type: Number } 8 | }); 9 | 10 | module.exports = model('guidAlmacenamiento', guidStoreSchema); -------------------------------------------------------------------------------- /src/Database/Models/UidStore.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose'); 2 | 3 | const uidStoreSchema = new Schema({ 4 | uid: { type: String }, 5 | user: { type: String }, 6 | name: { type: String }, 7 | numero: { type: Number }, 8 | }); 9 | 10 | module.exports = model('uidAlmacenamiento', uidStoreSchema); -------------------------------------------------------------------------------- /src/Database/Models/discordinfo.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose'); 2 | 3 | const discordInfoSchema = new Schema({ 4 | Servers: { type: String }, 5 | Users: { type: String }, 6 | Channels: { type: String } 7 | }); 8 | 9 | module.exports = model('discordinfo', discordInfoSchema); -------------------------------------------------------------------------------- /src/Database/Models/setArmaServer.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose'); 2 | 3 | const armaSchema = new Schema({ 4 | Arma3Ip: { type: String }, 5 | ArmaPort: { type: String }, 6 | GuildID: { type: String } 7 | }); 8 | 9 | module.exports = model('arma3ip', armaSchema); -------------------------------------------------------------------------------- /src/Database/Models/setdayzserver.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose'); 2 | 3 | const dayzSchema = new Schema({ 4 | DayzIp: { type: String }, 5 | DayzPort: { type: String }, 6 | GuildID: {type: String} 7 | }); 8 | 9 | module.exports = model('dayzip', dayzSchema); -------------------------------------------------------------------------------- /src/Helpers/GenericFunctions.js: -------------------------------------------------------------------------------- 1 | const formatUptime = (uptimeInSeconds) => { 2 | const days = Math.floor(uptimeInSeconds / 86400); 3 | const hours = Math.floor((uptimeInSeconds % 86400) / 3600); 4 | const minutes = Math.floor((uptimeInSeconds % 3600) / 60); 5 | const seconds = Math.floor(uptimeInSeconds % 60); 6 | 7 | return `${days}d ${hours}h ${minutes}m ${seconds}s`; 8 | }; 9 | 10 | module.exports = { 11 | formatUptime, 12 | }; -------------------------------------------------------------------------------- /src/Middlewares/LoggerMiddleware.js: -------------------------------------------------------------------------------- 1 | const winston = require('winston'); 2 | const expressWinston = require('express-winston'); 3 | 4 | const logger = expressWinston.logger({ 5 | transports: [ 6 | new winston.transports.Console() 7 | ], 8 | format: winston.format.combine( 9 | winston.format.colorize(), 10 | winston.format.json() 11 | ), 12 | meta: true, 13 | msg: "HTTP {{req.method}} {{req.url}}", 14 | expressFormat: true, 15 | colorize: false, 16 | ignoreRoute: function (req, res) { return false; } 17 | }); 18 | 19 | module.exports = logger; -------------------------------------------------------------------------------- /src/Models/Response/ErrorResponse.js: -------------------------------------------------------------------------------- 1 | class ErrorResponse { 2 | statusCode = null; 3 | error = null; 4 | message = null; 5 | 6 | constructor(statusCode, error, message) { 7 | this.statusCode = statusCode; 8 | this.error = error ? error : 'Error'; 9 | this.message = message ? message : 'Internal Server Error'; 10 | } 11 | } 12 | 13 | module.exports = { ErrorResponse }; -------------------------------------------------------------------------------- /src/Models/Response/FormaterResponse.js: -------------------------------------------------------------------------------- 1 | class FormaterResponse { 2 | result = null; 3 | 4 | constructor(result) { 5 | this.result = result; 6 | } 7 | } 8 | 9 | module.exports = { FormaterResponse }; -------------------------------------------------------------------------------- /src/Models/Response/ObtainGuidResponse.js: -------------------------------------------------------------------------------- 1 | class ObtainGuidResponse { 2 | guid = null; 3 | steamId = null; 4 | 5 | constructor(guid, steamId) { 6 | this.guid = guid ? guid : null; 7 | this.steamId = steamId ? steamId : null; 8 | } 9 | } 10 | 11 | module.exports = { ObtainGuidResponse }; -------------------------------------------------------------------------------- /src/Models/Response/ObtainUidResponse.js: -------------------------------------------------------------------------------- 1 | class ObtainUidResponse { 2 | cfToolsUid = null; 3 | bohemiaUid = null; 4 | steamId = null; 5 | 6 | constructor(cfToolsUid, bohemiaUid, steamId) { 7 | this.cfToolsUid = cfToolsUid ? cfToolsUid : null; 8 | this.bohemiaUid = bohemiaUid ? bohemiaUid : null; 9 | this.steamId = steamId ? steamId : null; 10 | } 11 | } 12 | 13 | module.exports = { ObtainUidResponse }; -------------------------------------------------------------------------------- /src/Routes/ApiRouter.js: -------------------------------------------------------------------------------- 1 | const { Router } = require('express'); 2 | const { ApiController } = require('../Controllers/ApiController'); 3 | const { HealthCheckController } = require('../Controllers/HealthCheckController'); 4 | const { ServersController } = require('../Controllers/ServersController'); 5 | const router = Router(); 6 | 7 | router.get('/guid', ApiController.guidController); 8 | router.get('/uid', ApiController.uidController); 9 | router.get('/health-check', HealthCheckController.healthCheck); 10 | 11 | router.get('/servers', ServersController.getServerInfo); 12 | router.get('/servers/games/list', ServersController.getGamesList); 13 | 14 | module.exports = router; -------------------------------------------------------------------------------- /src/WebServer.js: -------------------------------------------------------------------------------- 1 | const bodyParser = require('body-parser'); 2 | const express = require('express'); 3 | const logger = require('./Middlewares/LoggerMiddleware'); 4 | const swaggerUi = require('swagger-ui-express'); 5 | const swaggerDocument = require('../swagger.json'); 6 | 7 | class WebServer { 8 | constructor() { 9 | this.app = express(); 10 | this.port = process.env.API_PORT || 3000; 11 | this.prefix = '/api/v1'; 12 | this.middlewares(); 13 | this.routes(); 14 | } 15 | 16 | middlewares() { 17 | this.app.use(bodyParser.json()); 18 | this.app.use(bodyParser.urlencoded({ extended: true })); 19 | this.app.use(logger); 20 | } 21 | 22 | routes() { 23 | this.app.use(this.prefix, require('./Routes/ApiRouter')); 24 | this.app.use('/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); 25 | } 26 | 27 | listen() { 28 | this.app.listen(this.port, () => { 29 | console.log(`API Server on port: ${parseInt(this.port)}`); 30 | }) 31 | } 32 | } 33 | 34 | module.exports = { WebServer }; -------------------------------------------------------------------------------- /src/services/ApiService.js: -------------------------------------------------------------------------------- 1 | const { createHash } = require('crypto'); 2 | const { HttpConstants } = require('../Constants/HttpConstants'); 3 | const { GeneralConstants } = require('../Constants/GeneralConstants'); 4 | const { ErrorResponse } = require('../Models/Response/ErrorResponse'); 5 | const { ObtainGuidResponse } = require('../Models/Response/ObtainGuidResponse'); 6 | const { ObtainUidResponse } = require('../Models/Response/ObtainUidResponse'); 7 | 8 | class ApiService { 9 | 10 | static async obtainGuid(req) { 11 | if (!req.query.steam) return new ErrorResponse(HttpConstants.BAD_REQUEST, "Enter the query parameters", "/api/guid?steam=your-steam-id-64-here"); 12 | if (req.query.steam.length != 17) return new ErrorResponse(HttpConstants.BAD_REQUEST, "Argument must be 17 characters"); 13 | let bytes = []; 14 | try { 15 | for (let i = 0; i < 8; i++) { 16 | bytes.push(Number((BigInt(req.query.steam) >> (8n * BigInt(i))) & 0xFFn)) 17 | } 18 | let guid = createHash('md5').update(Buffer.from([0x42, 0x45, ...bytes])).digest('hex'); 19 | bytes = []; 20 | const response = new ObtainGuidResponse(guid, req.query.steam); 21 | return response; 22 | } catch (e) { 23 | return new ErrorResponse(HttpConstants.INTERNAL_SERVER_ERROR, "Fatal Error"); 24 | } 25 | } 26 | 27 | static uidService(req) { 28 | if (!req.query.steam) return new ErrorResponse(HttpConstants.BAD_REQUEST, "Enter the query parameters", "/api/uid?steam=your-steam-id-64-here"); 29 | if (req.query.steam.length != 17) return new ErrorResponse(HttpConstants.BAD_REQUEST, "Argument must be 17 characters"); 30 | try { 31 | let pwdToBase64 = createHash('sha256').update(req.query.steam).digest('base64'); 32 | let pwdReplace = pwdToBase64.replace(GeneralConstants.MAS_REGEX, GeneralConstants.GUION); 33 | let pwdFinally = pwdReplace.replace(GeneralConstants.BARRA_REGEX, GeneralConstants.GUION_BAJO); 34 | const response = new ObtainUidResponse(pwdFinally, pwdToBase64, req.query.steam); 35 | return response; 36 | } catch (e) { 37 | return new ErrorResponse(HttpConstants.INTERNAL_SERVER_ERROR, "Fatal Error"); 38 | } 39 | } 40 | } 41 | 42 | module.exports = { ApiService } -------------------------------------------------------------------------------- /src/services/MessageEventService.js: -------------------------------------------------------------------------------- 1 | class MessageEventService { 2 | 3 | static async sendLogsToChannel() { 4 | //TODO 5 | } 6 | } 7 | 8 | module.exports = { MessageEventService }; -------------------------------------------------------------------------------- /src/services/ServersService.js: -------------------------------------------------------------------------------- 1 | const GD = require('gamedig'); 2 | const { GameList } = require('../Constants/GameListConstants'); 3 | const { HttpConstants } = require('../Constants/HttpConstants'); 4 | const { ErrorResponse } = require('../Models/Response/ErrorResponse'); 5 | 6 | class ServersService { 7 | 8 | static async getServerInfo(req) { 9 | const query = req.query; 10 | if (!query?.game) return new ErrorResponse(HttpConstants.BAD_REQUEST, "Enter game query parameter", "/api/servers?game=arma3"); 11 | if (!query?.host) return new ErrorResponse(HttpConstants.BAD_REQUEST, "Enter host query parameter", "/api/servers/game=arma3?host=your-ip-here"); 12 | let game = Object.values(GameList); 13 | let findGame; 14 | for (const g of game) { 15 | const find = Object.keys(g).find(key => key === query.game); 16 | if (find !== undefined) { 17 | findGame = g[find]; 18 | break; 19 | } 20 | } 21 | if (!game || !findGame) return new ErrorResponse(HttpConstants.BAD_REQUEST, "Game or Service not found", "/api/servers?game=dayz"); 22 | try { 23 | const ping = await GD.query({ 24 | type: query.game.toLowerCase(), 25 | host: query.host, 26 | port: query?.port ? query.port : 2302 27 | }); 28 | return ping; 29 | } catch (e) { 30 | return new ErrorResponse(HttpConstants.BAD_REQUEST, "Error to fetch the server"); 31 | } 32 | } 33 | 34 | static async getGamesList() { 35 | const games = GameList; 36 | return games; 37 | } 38 | } 39 | 40 | module.exports = { ServersService }; -------------------------------------------------------------------------------- /swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.3", 3 | "info": { 4 | "title": "SteamId64ToGuid - Public API", 5 | "version": "20220928" 6 | }, 7 | "servers": [ 8 | { 9 | "url": "https://apidev.steamid64toguid.cf/api/v1" 10 | } 11 | ], 12 | "tags": [ 13 | { 14 | "name": "Convert" 15 | }, 16 | { 17 | "name": "Servers" 18 | } 19 | ], 20 | "paths": { 21 | "/guid": { 22 | "get": { 23 | "tags": [ 24 | "Convert" 25 | ], 26 | "summary": "Convert Steam ID 64 to GUID", 27 | "parameters": [ 28 | { 29 | "name": "steam", 30 | "in": "query", 31 | "description": "User Steam ID", 32 | "required": true, 33 | "schema": { 34 | "type": "string", 35 | "default": 76561199088563020 36 | } 37 | } 38 | ], 39 | "responses": { 40 | "200": { 41 | "description": "Successful response -", 42 | "content": { 43 | "application/json": { 44 | "schema": { 45 | "type": "object", 46 | "properties": { 47 | "result": { 48 | "$ref": "#/components/schemas/GuidSchemaResponse" 49 | } 50 | } 51 | } 52 | } 53 | } 54 | }, 55 | "400": { 56 | "description": "Bad Request -", 57 | "content": { 58 | "application/json": { 59 | "schema": { 60 | "type": "object", 61 | "properties": { 62 | "statusCode": { 63 | "type": "number", 64 | "format": "number", 65 | "example": 400 66 | }, 67 | "error": { 68 | "type": "string", 69 | "format": "string", 70 | "example": "Enter the query parameters" 71 | }, 72 | "message": { 73 | "type": "string", 74 | "format": "string", 75 | "example": "/api/guid?steam=your-steam-id-64-here" 76 | } 77 | } 78 | } 79 | } 80 | } 81 | } 82 | } 83 | } 84 | }, 85 | "/uid": { 86 | "get": { 87 | "tags": [ 88 | "Convert" 89 | ], 90 | "summary": "Convert Steam ID 64 to GUID", 91 | "parameters": [ 92 | { 93 | "name": "steam", 94 | "in": "query", 95 | "description": "User Steam ID", 96 | "required": true, 97 | "schema": { 98 | "type": "string", 99 | "default": 76561199088563020 100 | } 101 | } 102 | ], 103 | "responses": { 104 | "200": { 105 | "description": "Successful response -", 106 | "content": { 107 | "application/json": { 108 | "schema": { 109 | "type": "object", 110 | "properties": { 111 | "result": { 112 | "$ref": "#/components/schemas/UidSchemaResponse" 113 | } 114 | } 115 | } 116 | } 117 | } 118 | }, 119 | "400": { 120 | "description": "Bad Request -", 121 | "content": { 122 | "application/json": { 123 | "schema": { 124 | "type": "object", 125 | "properties": { 126 | "statusCode": { 127 | "type": "number", 128 | "format": "number", 129 | "example": 400 130 | }, 131 | "error": { 132 | "type": "string", 133 | "format": "string", 134 | "example": "Enter the query parameters" 135 | }, 136 | "message": { 137 | "type": "string", 138 | "format": "string", 139 | "example": "/api/uid?steam=your-steam-id-64-here" 140 | } 141 | } 142 | } 143 | } 144 | } 145 | } 146 | } 147 | } 148 | }, 149 | "/servers": { 150 | "get": { 151 | "tags": [ 152 | "Servers" 153 | ], 154 | "summary": "Get remote game server information", 155 | "parameters": [ 156 | { 157 | "name": "game", 158 | "in": "query", 159 | "description": "Game name", 160 | "required": true, 161 | "schema": { 162 | "type": "string", 163 | "example": "arma3" 164 | } 165 | }, 166 | { 167 | "name": "host", 168 | "in": "query", 169 | "description": "Game server host (ip)", 170 | "required": true, 171 | "schema": { 172 | "type": "string", 173 | "example": "127.0.0.1" 174 | } 175 | }, 176 | { 177 | "name": "port", 178 | "in": "query", 179 | "description": "Game port", 180 | "required": false, 181 | "schema": { 182 | "type": "string", 183 | "default": 2302 184 | } 185 | } 186 | ], 187 | "responses": { 188 | "200": { 189 | "description": "Successful response -", 190 | "content": { 191 | "application/json": { 192 | "schema": { 193 | "type": "object", 194 | "properties": { 195 | "result": { 196 | "$ref": "#/components/schemas/GameServerResponse" 197 | } 198 | } 199 | } 200 | } 201 | } 202 | }, 203 | "400": { 204 | "description": "Bad Request -", 205 | "content": { 206 | "application/json": { 207 | "schema": { 208 | "type": "object", 209 | "properties": { 210 | "statusCode": { 211 | "type": "number", 212 | "format": "number", 213 | "example": 400 214 | }, 215 | "error": { 216 | "type": "string", 217 | "format": "string", 218 | "example": "Enter game query parameter" 219 | }, 220 | "message": { 221 | "type": "string", 222 | "format": "string", 223 | "example": "/api/servers?game=arma3" 224 | } 225 | } 226 | } 227 | } 228 | } 229 | } 230 | } 231 | } 232 | }, 233 | "/servers/games/list": { 234 | "get": { 235 | "tags": [ 236 | "Servers" 237 | ], 238 | "summary": "Get game list", 239 | "responses": { 240 | "200": { 241 | "description": "Successful response -", 242 | "content": { 243 | "application/json": { 244 | "schema": { 245 | "type": "object", 246 | "properties": { 247 | "result": { 248 | "$ref": "#/components/schemas/GameListResponse" 249 | } 250 | } 251 | } 252 | } 253 | } 254 | } 255 | } 256 | } 257 | } 258 | }, 259 | "components": { 260 | "schemas": { 261 | "GuidSchemaResponse": { 262 | "type": "object", 263 | "properties": { 264 | "guid": { 265 | "type": "string", 266 | "format": "string", 267 | "example": "bcf8c798fe19eb44a9dbbcd8b831fd85" 268 | }, 269 | "steamId": { 270 | "type": "string", 271 | "format": "string", 272 | "example": "76561199088563030" 273 | } 274 | } 275 | }, 276 | "UidSchemaResponse": { 277 | "type": "object", 278 | "properties": { 279 | "cfToolsUid": { 280 | "type": "string", 281 | "format": "string", 282 | "example": "8r8LJKISEFtFODaYtkrBupF6kf_ebhPnI2U6R0IeftQ=" 283 | }, 284 | "bohemiaUid": { 285 | "type": "string", 286 | "format": "string", 287 | "example": "8r8LJKISEFtFODaYtkrBupF6kf/ebhPnI2U6R0IeftQ=" 288 | }, 289 | "steamId": { 290 | "type": "string", 291 | "format": "string", 292 | "example": "76561199088563030" 293 | } 294 | } 295 | }, 296 | "GameServerResponse": { 297 | "type": "object", 298 | "properties": { 299 | "hugeGameServerInformation": { 300 | "type": "object", 301 | "format": "object" 302 | } 303 | } 304 | }, 305 | "GameListResponse": { 306 | "type": "object", 307 | "properties": { 308 | "games": { 309 | "type": "object", 310 | "format": "object", 311 | "example": { 312 | "arma3": "Arma 3", 313 | "arma2": "Arma 2", 314 | "dayz": "Dayz Standalone", 315 | "dayzmod": "Dayz Mod 2013", 316 | "csgo": "Counter-Strike: Global Offensive", 317 | "cs16": "Counter-Strike 1.6", 318 | "fivem": "FiveM", 319 | "samp": "San Andreas Multiplayer", 320 | "mtasa": "MTA San Andreas", 321 | "mtavc": "MTA Vice City", 322 | "minecraft": "Minecraft", 323 | "minecraftpe": "Minecraft: Pocket Edition", 324 | "ps": "Post Scriptum", 325 | "przomboid": "Project Zomboid", 326 | "rust": "Rust", 327 | "rfactor": "rFactor", 328 | "squad": "Squad", 329 | "valheim": "Valheim", 330 | "7d2d": "7 Days to Die", 331 | "aoe2": "Age of Empires 2", 332 | "arkse": "Ark Survival Evolved", 333 | "assettocorsa": "Assetto Corsa", 334 | "conanexiles": "Conan Exiles", 335 | "garrysmod": "Garrys Mod", 336 | "hll": "Hell Let Loose", 337 | "insurgency": "Insurgency", 338 | "insurgencysandstorm": "Insurgency: Sandstorm", 339 | "killingfloor": "Killing Floor", 340 | "killingfloor2": "Killing Floor 2", 341 | "left4dead": "Left 4 Dead", 342 | "left4dead2": "Left 4 Dead 2", 343 | "openttd": "OpenTTD" 344 | } 345 | }, 346 | "services": { 347 | "type": "object", 348 | "format": "object", 349 | "example": { 350 | "teamspeak3": "TeamSpeak 3", 351 | "teamspeak2": "TeamSpeak 2", 352 | "ventrilo": "Ventrilo", 353 | "discord": "Discord" 354 | } 355 | } 356 | } 357 | } 358 | } 359 | } 360 | } --------------------------------------------------------------------------------