Create dynamic custom shields for your GitHub Readme!

This article explains how to create a custom dynamic shield that will change over time using shields.io.

Ever wanted to display your discord bot servers count on your GitHub repository?
The article covers that too.

I implemented this for my discord bot, Valorina.

GitHub logo sanjaybaskaran01 / Valorina

Discord πŸ€– to never miss a Valorant skin drop!

valorina Issues


Logo

Valorina

Discord bot for all valorant skin enthusiasts

invite

Top.gg Β· Report Bug Β· Request Feature

Table of Contents

About The Project

Check the skins available in your store and balance using Valorina without having to open the Valorant client and get notified whenever your favourite skins are up for grabs! πŸ₯³ 🎊

Built With

Features and Commands


+help
Summary of all available commands

+help

+adduser <username> <password> <region>
Adds the user (IN DM COMMAND)

+adduser

+store <username> <region>
Shows all the available weapon skins in your store

+store

+bal <username> <region>
Shows the balance of your account

+bal

+reminder <username> <region> <skin name>
Sets reminder of your favourite skin and notifies you if it is available in your store (IN DM COMMAND)

+reminder

Automated Reminders

reminderoutput

Contributing

Contributions are what make the open source community such an…

Table of Contents

Prerequisites

  1. MongoDB
  2. Discord.py or Discord.js
  3. Free Vercel account or any server to host backend endpoint

What we are going to accomplish

Build a Github badge that display the server count of the bot and dynamically update when added to a new server

File structure

.
β”œβ”€β”€ server_count (Backend folder)
β”‚Β Β  β”œβ”€β”€ index.js
β”‚Β Β  β”œβ”€β”€ models
β”‚Β Β  β”‚Β Β  └── server.js
β”‚Β Β  β”œβ”€β”€ package.json
β”‚Β Β  β”œβ”€β”€ package-lock.json
β”‚Β Β  └── vercel.json
└── Valorina (Bot folder)
    β”œβ”€β”€ bot.py
    β”œβ”€β”€ db.py

How we are going to accomplish it

MongoDB and Bot.py

Create a new collection in mongoDB

Create a new document in your mongoDB collection

Copy the ID of the document which is 619637ac508090df22a468b5 for me

Now on your db.py, we are creating a function which will find this document,create a field in it called "server_count" and set the count

# db.py
from pymongo import MongoClient

MONGO = "mongodb+srv://name:[email protected]" # Mongo string 
ID = "619637ac508090df22a468b5" # ID of Mongo document that will contain the server count
cluster = MongoClient(MONGO)
db = cluster["discord"] # Name of your cluster

def updateServerCount(count):
    collection = db['servers'] # Name of the collection in your cluster
    collection.update_one(
            {'_id':ObjectId(ID)},
            {"$set":{'server_count':count}})

Now on your bot.py, we will use updateServerCount function whenever the bot joins a new server

# bot.py

import discord
import db
# All other imports

# Create a bot event or client event depending on what you are using

@bot.event
async def on_guild_join(guilds):
    count = len(bot.guilds) # array with all the servers but we need just its length
    db.updateServerCount(count) # function that will update server count

Creating the Backend API endpoint to generate a badge

npm init -y
npm i express
npm i mongoose
npm i -g vercel

Create a new folder called model for the schema of the document

// /models/server.js

const mongoose = require('mongoose');

const { Schema } = mongoose;

const ServerSchema = new Schema({
    server_count: {
        type: Number,
        required: [true, 'server count is required']
    }
})

const Servers = mongoose.model('servers', ServerSchema) // servers is the name of the collection in mongoDB

module.exports = Servers;

Create an index.js file in the folder

// index.js

const express = require('express');
const app = express();


const mongoose = require('mongoose')

const MONGO = "mongodb+srv://name:[email protected]" 
// Mongo string 
const ID = "619637ac508090df22a468b5" 
// ID of Mongo document that will contain the server count

mongoose.connect(MONGO, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
});

mongoose.Promise = global.Promise;

const Servers = require('./models/server');

const port = process.env.PORT || 3001


app.get('/api', async (req, res) => {
    const servers_count = await Servers.findById(ID)
    res.setHeader('Content-Type', 'application/json')
    res.json({ schemaVersion: 1, label: "Valorina #6711", message: `Server count: ${servers_count['server_count']}`, namedLogo: "Discord", labelColor: "586AEA", style: "for-the-badge", logoColor: "white", color: "FE424F" });
})

app.listen(port, () => {
    console.log(`listening to port ${port}`);
})

Now let us look at what we have created

node index.js
listening to port 3001

If everything went as instructed we should receive this when we open localhost:3001/api

We have successfully built an endpoint which sheilds.io can utilise

Customise the shield

Please feel free to customise the shield to your liking

Once done we can head over to shields.io/endpoint and try previewing the shield.

But we stumble into a problem here. shields.io does not accept endpoints from localhosts we must host this backend that we have created somewhere.

Vercel comes handy in this scene.

Hosting the backend using vercel

Please feel free to host the backend in any cloud services, we are using Vercel since it is free.

run the command vercel in root of backend

? Set up and deploy β€œ~/Desktop/username/vercel-node-app”? [Y/n] y
? Which scope do you want to deploy to? username
? Link to existing project? [y/N] n
? What’s your project’s name? server-count
? In which directory is your code located? ./
No framework detected. Default Project Settings:
- Build Command: `npm run vercel-build` or `npm run build`
- Output Directory: `public` if it exists, or `.`
- Development Command: None
? Want to override the settings? [y/N] n

We need to create a vercel.json in the root of backend,

{
    "version": 2,
    "builds": [
        {
            "src": "./index.js",
            "use": "@vercel/node"
        }
    ],
    "routes": [
        {
            "src": "/(.*)",
            "dest": "/"
        }
    ]
}

Now run the command vercel again and we will find fully working deployed link which has all the routes, copy that link eg: server-count-sanjaybaskaran01.vercel.app/api

Head over to shields.io/endpoint
shields.io endpoint

Voilà! 🎊🎊

We have successfully created a Github shield for our discord bot which will dynamically display the amount of servers in which the bot is a part of.

18