This tutorial is part of the ro.py tutorial set.
To view more ro.py tutorials and learn more about ro.py,
visit the Discord server, main topic, documentation, or GitHub repository.
In this tutorial, I’ll teach you how to add Roblox features to your discord.py bots with ro.py, the Roblox Web API wrapper for Python 3.
When you finish the tutorial, you’ll have made whois
, shout
, exile
, promote
, demote
, and setrank
commands.
We’ll start with my discord.py bot template, but you’ll be able to follow this tutorial with your own bots (which is recommended, as this is a ro.py tutorial and I won’t be going over discord.py!)
If you are cloning this template, place a file named .env
in the same directory as the template, and place your token in it like so:
DISCORDTOKEN=tokengoeshere
discord.py - Bot Template
from discord.ext.commands import Bot, has_permissions
from discord import Embed
from discord.utils import escape_markdown, escape_mentions # We will use this later!
from dotenv import load_dotenv
import os
load_dotenv() # Load environment variables from .env file.
bot = Bot(
command_prefix="r!", # r! will be our prefix
case_insensitive=True # e.g. r!help is the same as r!HELP or r!hElP
)
@bot.event
async def on_ready():
print(f"Logged in as {bot.user}")
@bot.command()
async def test(ctx):
await ctx.send("Hello World") # Replies with "Hello World"
bot.run(os.getenv("DISCORDTOKEN")) # Grab the DISCORDTOKEN env from our .env file
To begin, just start with Part 1 below and keep going! Don’t worry, it’s not hard.
Installation/Setup
To begin, you’ll need to install ro.py. You can install it from PyPI (pip), but I suggest cloning from GitHub to get the latest features.
We’ll use this command to install ro.py:
pip install roblox
(Use pip3
instead of pip
to ensure you’re using the Python 3.x version of pip if you have Python 2.x installed.)
Next, import the ro.py client at the top of your file, right where the rest of the imports are:
from ro_py import Client
Then, right above the line where you create your Bot, add this line:
roblox = Client()
The area where you generate your bot will now look like this:
bot = Bot(...)
roblox = Client()
This generates a ro.py client named roblox
that we will use later.
This tutorial will go over some commands that do require authentication, which means you’ll need to create a new Roblox account (or use your own, but it’s not recommended) and grab your ROBLOSECURITY cookie and pass it to the client like so:
roblox = Client("ROBLOSECURITY HERE")
You can grab it in the padlock menu on Chromium-based browsers or through the Developer Tools > Settings menu. You can also grab it though the Developer Tools on Firefox.
Do not share this cookie! It can give an attacker access to your account.
Please note that once you log into your alt and grab the cookie, logging out will invalidate that cookie and it won’t work again.
To get around this, you can open an incognito window and grab the cookie there, then close that window, or just delete the cookie once you’re done without pressing the Logout button.
whois command
At this point, things start to differ from a normal ro.py application because we won’t need to grab the event loop and call run_until_complete
(if you don’t know what that means, don’t worry!)
To start, we’ll add a whois
command that grabs a Roblox user and their information. We’ll start by adding the command:
@bot.command()
async def whois(ctx, username):
We’ll then grab the user using get_user_by_username
like so:
@bot.command()
async def whois(ctx, username):
user = await client.get_user_by_username(username)
We can now generate an embed or send a message containing information about our user. I’ll start with an embed, but you can get as fancy as you want!
@bot.command()
async def whois(ctx, username):
user = await roblox.get_user_by_username(username)
embed = Embed(title=f"Info for {user.name}")
embed.add_field(
name="Username",
value="`" + user.name + "`"
)
embed.add_field(
name="Display Name",
value="`" + user.display_name + "`"
)
embed.add_field(
name="User ID",
value="`" + str(user.id) + "`"
)
embed.add_field(
name="Description",
value="```" + (escape_markdown(user.description or "No description")) + "```"
)
await ctx.send(embed=embed)
We’re using escape_mentions
and escape_markdown
to prevent users from setting their status to @everyone
or placing Discord message markdown in a message.
This command will look something like this:
It works, but it’s a bit boring. Let’s add the user’s headshot in the top right corner of the embed!
To do this, we’ll need to import some extra things at the top of our file. Add this to your imports:
from ro_py.thumbnails import ThumbnailSize, ThumbnailType
Add this right before your ctx.send
:
avatar_image = await user.thumbnails.get_avatar_image(
shot_type=ThumbnailType.avatar_headshot, # headshot
size=ThumbnailSize.size_420x420, # high resolution thumbnail
is_circular=False # square thumbnail
)
embed.set_thumbnail(
url=avatar_image
)
Now our embed will look like this:
Looks pretty neat! You are free to advance to the next commands.
shout command
Warning: make sure to lock this command behind some sort of permission check or others may be able to shout in your group without your permission!
This one’s fairly simple. All we have to do is store a group somewhere and call await group.shout(newshout)
when the time comes.
client.get_group
caches objects, so it’s okay to grab it in a command.
@bot.command()
@has_permissions(manage_guild=True) # Guild managers only.
async def shout(ctx, *, shout_text):
group = await roblox.get_group(7819173) # Group ID here
await group.shout(shout_text)
await ctx.send("Sent shout.")
If we want to be able to shout in any group the client has access to, we can also take in a group ID as a parameter, like so:
@bot.command()
@has_permissions(manage_guild=True) # Guild managers only.
async def shout(ctx, group_id: int, *, shout_text):
group = await roblox.get_group(group_id)
await group.shout(shout_text)
await ctx.send("Sent shout.")
An error will be raised on the shout event if something goes wrong, which your error handler should catch.
exile command
Again, not a hard one! All we have to do is take in a username and exile that user from the group. This time, instead of grabbing a User
, we’ll grab a Member
.
@bot.command()
@has_permissions(manage_guild=True) # Guild managers only.
async def exile(ctx, username):
group = await roblox.get_group(7819173) # Group ID here
member = await group.get_member_by_username(username)
await member.exile()
await ctx.send("Exiled user.")
Similar to the shout
command, we can also exile users on a specific group:
@bot.command()
@has_permissions(manage_guild=True) # Guild managers only.
async def exile(ctx, group_id: int, username):
group = await roblox.get_group(group_id) # Group ID here
member = await group.get_member_by_username(username)
await member.exile()
await ctx.send("Exiled user.")
promote/demote/setrank commands
Now we’re getting fancy! We’ll add a promote
and demote
command (which will go up a rank an down a rank number respectively) and also a setrank
command (which will set the user to a specific rank ID)
We’ll start with promote
and demote
:
@bot.command()
@has_permissions(manage_guild=True) # Guild managers only.
async def promote(ctx, username):
group = await roblox.get_group(7819173) # Group ID here
member = await group.get_member_by_username(username)
await member.promote()
await ctx.send("Promoted user.")
@bot.command()
@has_permissions(manage_guild=True) # Guild managers only.
async def demote(ctx, username):
group = await roblox.get_group(7819173) # Group ID here
member = await group.get_member_by_username(username)
await member.demote()
await ctx.send("Promoted user.")
You can also add a group_id
parameter and pass it to get_group
if your workflow requires managing multiple groups.
Next, we’ll add a setrank
command for specific ranks. This will use the same ID system used by ranks in your group settings:
@bot.command()
@has_permissions(manage_guild=True) # Guild managers only.
async def setrank(ctx, username, rank: int):
if 255 >= rank >= 1: # Make sure rank is in allowed range
group = await roblox.get_group(7819173) # Group ID here
member = await group.get_member_by_username(username)
await member.setrole(rank) # Sets the rank
await ctx.send("Promoted user.")
else:
await ctx.send("Rank must be at least 1 and at most 255.")
If you want more control over promotions, you can grab a list of roles (note the difference) with await group.get_roles()
.
Continue with ro.py
The same things that I taught you here can be used to create very advanced Discord-Roblox bots! I use ro.py for FiveFive, an advanced Discord bot:
I encourage you to keep learning about ro.py and to continue adding features to your bot! You can join our Discord server if you have more questions (or reply to this topic, I’ll be happy to help you with that!) I encourage you to continue with ro.py, and if you’re feeling nice you can also contribute to the project by implementing more APIs that aren’t currently part of the project.
Thank you for following this tutorial, and please let me know if you’d like me to write any more ro.py tutorials as part of this tutorial set!
This tutorial goes nowhere near the extent of what ro.py can do, and there are many other commands I plan to add to this tutorial in the future! Please let me know if there’s anything you’d like me to add.