Recreate the Discord Widget using the Discord API

Viewed 1232

As of now, I am creating my own styled widget using the JSON from https://discordapp.com/api/servers/GUILD-ID/widget.json, which works fine so far. However, this JSON is limited to 99 users, and that's a problem for me.

So I thought, I could just re-create it, using the official Discord API. However, there is some information, I can't find in the API, or maybe I'm just blind.

  1. I am missing the information, which user is currently in which voice channel
  2. I am missing the online status of a user
  3. I am missing the avatar URL
  4. Whether the fields muteand deaf exist within the user object, they are null/empty, while the widget.json displays the correct information

So a user object in the widget.json looks like this:

{
    id: "0",
    username: "xxxx",
    discriminator: "0000",
    avatar: null,
    status: "online",
    deaf: false,
    mute: false,
    self_deaf: true,
    self_mute: true,
    suppress: false,
    channel_id: "555555555555555555",
    avatar_url: "https://cdn.discordapp.com/widget-avatars/XXXXXXXXXXXXXXX"
}

while the API returns this:

{
    user: {
    id: "999999999999999999",
    username: "xxxx",
    avatar: "257281f9b2aa93be7c12f5c49e122ca3",
    discriminator: "1234",
    public_flags: 576
    },
    roles: [
        "123456789123456789",
        "987654321987654321"
    ],
    nick: "yyyy",
    premium_since: null,
    joined_at: "1970-01-01T00:00:00.000000+00:00",
    is_pending: false,
    mute: false,
    deaf: false
}

which is pretty much unusable for my case.

1 Answers

I was just messing around with this earlier today here is what I came up with so far if you never figured that out

css

        * {
            box-sizing: border-box;
        }
        
        html,
        body {
            font-family: Whitney, "Helvetica Neue", Helvetica, Arial, sans-serif;
            color: #eeeeef;
            background-color: #36393f;
            display: flex;
            justify-content: flex-start;
            align-items: baseline;
            align-content: flex-start;
            flex-wrap: wrap;
            flex-direction: row;
        }
        
        p {
            margin: 3;
        }
        
        .sticky {
            position: -webkit-sticky;
            position: sticky;
            top: 0;
            float: left;
        }
        
        a {
            background-color: #5865F2;
            box-shadow: inset 0 -0.6em 0 -0.35em rgb(0 0 0 / 17%);
            color: #eeeeef;
            padding: 1em 1.5em;
            position: relative;
            text-decoration: none;
            text-transform: uppercase;
            z-index: 5;
            border-radius: 0.5rem;
            font-weight: bold;
            font-size: 1.5rem;
            float: right;
        }
        
        a:hover {
            transition: all 1.5s;
            box-shadow: inset 0 0 100px 100px rgb(255 255 255 / 30%);
        }
        
        a:active {
            box-shadow: none;
            top: 5px;
        }
        
        header {
            margin: 50px;
        }
        
        h1 {
            font-size: 4rem;
            z-index: 3;
            text-shadow: 3px 3px 4px #000000a6;
        }
        
        .member {
            padding: 8px;
            font-size: 1.3rem;
            margin: 5;
            text-shadow: 1.5px 1.5px 16px #00000025;
        }
        
        img {
            border-radius: 5px;
        }
        
        .memberText {
            position: absolute;
            margin-top: 5.8px;
            margin-left: 25px;
            font-weight: bold;
        }
        
        br {
            display: block;
            margin: 10px 0;
            line-height: 22px;
            content: " ";
        }
        
        #users {
            box-shadow: 20px 3em 20px 1em rgb(0 0 0 / 5%);
        }
        
        @media only screen and (max-width: 600px) {
            #wrap {
                width: 300px;
                background-image: linear-gradient(to left, transparent, #1d1e2280);
            }
        }

meta and script tags

<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://kit.fontawesome.com/6c4ec84abe.js" crossorigin="anonymous"></script>

body html


<body>

    <header class="sticky"></header>

    <div id="users">
    </div>
</body>

JS (I usually load at the bottom of the body tag or load it in with a tag when messing with DOM elements)

And to get the right JSON for the widget see the picture below

$.getJSON('https://discord.com/api/guilds/633515516207693864/widget.json', function(data) {

        var members = data.members;

        var title = `<h1>${data.name}</h1>
            <p><a href="${data.instant_invite}"" target="_blank"><i class="fa-brands fa-discord"></i> Join Now</a></p>`;

        for (var member in members) {

            var deaf = (members[member].deaf) ? "<font color='red'><i class='fa-solid fa-headphones'></i></font>" : "";
            var mute = (members[member].mute) ? "<font color='red'><i class='fa-solid fa-microphone-slash'></i></font>" : "";

            var gameCheck = (!members[member].game) ? `<span style="font-weight:100;font-style:italic;"></span>` : `<span style="font-weight:100;font-style:italic;">Playing ${members[member].game.name}</span>`;

            if (members[member].status === "online") {
                status = `<i class='fa-solid fa-circle' style='color:#00ff00ba;font-size:1rem;'></i>`;
            } else if (members[member].status === "idle") {
                status = `<i class="fa-solid fa-moon" style='color:#d9d93be6;font-size:1rem;'></i>`;
            }

            let memberItem = `<img src="${members[member].avatar_url}" style="height:100px; width:auto;margin-right:8px;"><span class="memberText">${status} ${members[member].username}<br><i style='font-size:1rem;font-weight:100 !important;margin-top:5px;'>${gameCheck}<br>${mute} ${deaf}</i></span>`;
            var onlineUsers = (members[member].username == "Hide Bot/User 1" || members[member].username == "Hide Bot/User 2") ? `` : `<div class='member'>${memberItem}</div>`;

            $("#users").append(`${onlineUsers}`);
        }

        $("header").html(title);

    });

Also here is a screenshot to get your JSON Api urlserver settings > widget > JSON API

Related