DEV Community

Cover image for Create dynamic custom shields for your GitHub Readme!
Sanjay Kumar Baskaran
Sanjay Kumar Baskaran

Posted on

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

valorina-badge

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
Enter fullscreen mode Exit fullscreen mode

How we are going to accomplish it

MongoDB and Bot.py

Create a new collection in mongoDB

new collection

Create a new document in your mongoDB collection

document creation

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:password@etcetc.mongodb.net" # 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}})
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

Creating the Backend API endpoint to generate a badge

npm init -y
npm i express
npm i mongoose
npm i -g vercel
Enter fullscreen mode Exit fullscreen mode

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;

Enter fullscreen mode Exit fullscreen mode

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:password@etcetc.mongodb.net" 
// 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}`);
})

Enter fullscreen mode Exit fullscreen mode

Now let us look at what we have created

node index.js
listening to port 3001
Enter fullscreen mode Exit fullscreen mode

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

localhost

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

Customise the shield

Please feel free to customise the shield to your liking

shields.io

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
Enter fullscreen mode Exit fullscreen mode

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

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

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.

Discussion (5)

Collapse
pragati1610 profile image
Pragati1610

good read πŸ€—

Collapse
advit profile image
Advit

Really well written article. Was looking for something with this content for quite a while. Thank you so much πŸ™

Collapse
andypiper profile image
Andy Piper

This is helpful, thanks for sharing!

Collapse
dustvictory profile image
Ashwin Kumar

This has shown me a whole new way to create custom shields. Keep writing more articles and helping others grow. Thanks πŸ™πŸ»

Collapse
ameeshagireesh profile image
Ameesha Gireesh

Detailed and well-written article, thanks for sharing the knowledge!πŸ‘πŸΎ