Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Suhail/cogs/clear.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import discord
from discord.ext import commands

class Clear(commands.Cog):

def __init__(self, bot): self.bot = bot

@commands.command()
async def clear(self, ctx, num: int):
try:
await ctx.channel.purge(limit=num)
except discord.Forbidden:
await ctx.send("Oops i can't do that rip")

def setup(bot):
bot.add_cog(Clear(bot))
20 changes: 20 additions & 0 deletions Suhail/cogs/error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from inspect import trace
import discord
from discord.ext import commands
import traceback

class Error(commands.Cog):

def __init__(self, bot):
self.bot = bot

@commands.Cog.listener()
async def on_command_error(self, ctx, error):
if isinstance(error, commands.BadArgument):
await ctx.send("I only accept numbers smh")
else:
traceback.print_exception(type(error), error, error.__traceback__)


def setup(bot):
bot.add_cog(Error(bot))
31 changes: 31 additions & 0 deletions Suhail/cogs/hi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import discord
from discord.ext import commands

class Hi(commands.Cog):

def __init__(self, bot: commands.Bot):
self.bot = bot

@commands.command()
async def ping(self, ctx):
return await ctx.send(f"Pong! :ping_pong: Latency: {round(self.bot.latency*1000, 2)}ms")

@commands.command()
async def hi(self, ctx, name = None):
name = name or ctx.author.display_name
await ctx.send(f"hello {name}!")

@commands.command()
async def greet(self, ctx):
await ctx.author.send("Private Greeting oooooooooo")

@commands.command()
async def sort(self, ctx, *args):
await ctx.send("\n".join(sorted(args)))

@commands.command()
async def logo(self, ctx):
await ctx.send(file=discord.File("logo.png"))

def setup(bot):
bot.add_cog(Hi(bot))
33 changes: 33 additions & 0 deletions Suhail/cogs/random.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import aiohttp
import discord
import random
from discord.ext import commands

class Random(commands.Cog):

def __init__(self, bot):
self.bot = bot

@commands.command()
async def flip(self, ctx, count: int):
if count < 0: return await ctx.send("Can't flip a negative number of coins")
if count == 0: return await ctx.send("Well... you flipped nothing so... Nothing")
await ctx.send(" ".join(random.choice(["H", "T"]) for x in range(count)))

@commands.command()
async def roll(self, ctx, count: int):
print("HERE")
if count < 0: return await ctx.send("Can't roll a negative number of dice")
if count == 0: return await ctx.send("Well... you rolled nothing so... Nothing")

await ctx.send(" ".join(str(random.randint(1, 6)) for x in range(count)))

@commands.command()
async def cat(self, ctx):
async with aiohttp.ClientSession() as session:
async with session.get("https://api.thecatapi.com/v1/images/search") as resp:
data = await resp.json()
return await ctx.send(data[0]["url"])

def setup(bot):
bot.add_cog(Random(bot))
93 changes: 93 additions & 0 deletions Suhail/cogs/twitter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import aiohttp
import os
from dateutil import parser
import discord
from discord.ext import commands

class Twitter(commands.Cog):

def __init__(self, bot):
self.bot = bot
self.token = os.environ["TWITTER_TOKEN"]
self.headers = {
"Authorization": f"Bearer {self.token}"
}

@commands.group(invoke_without_command=True)
async def twitter(self, ctx: commands.Context):
return await ctx.send_help("twitter")

@twitter.command()
async def lasttweet(self, ctx, username: str):
tdata, error = await self.get_user_by_name(username)
if error:
return await ctx.send(tdata["errors"][0]["detail"])
tweet, metrics, timestamp = await self.get_latest_tweet(tdata["data"]["id"])

timestamp = parser.parse(timestamp)

embed = discord.Embed(
title=f"{username}'s last tweet",
description = tweet,
color=0x00ff00,
timestamp = timestamp,
)

embed.add_field(name="Likes", value=metrics["like_count"])
embed.add_field(name="RTs", value=metrics["retweet_count"])
embed.add_field(name="Quote Tweets", value=metrics["quote_count"])
embed.add_field(name="Replies", value=metrics["reply_count"])

embed.set_footer(text="Created at")


await ctx.send(embed=embed)

@twitter.command()
async def userinfo(self, ctx, username: str):

tdata, error = await self.get_user_by_name(username)
if error:
return await ctx.send(tdata["errors"][0]["detail"])

embed = discord.Embed(
title=f"@{username}",
timestamp = parser.parse(tdata["data"]["created_at"]),
color = 0x00ff00
)
embed.add_field(name="Name",value=tdata["data"]["name"], inline=False)
embed.add_field(name="Bio",value=tdata["data"]["description"], inline=False)
embed.add_field(name="Followers", value=tdata["data"]["public_metrics"]["followers_count"])
embed.add_field(name="Following", value=tdata["data"]["public_metrics"]["following_count"])
embed.add_field(name="Tweets", value=tdata["data"]["public_metrics"]["tweet_count"])
embed.set_footer(text="Created at")
embed.set_thumbnail(url=tdata["data"]["profile_image_url"])

await ctx.send(embed=embed)


async def get_user_by_name(self, username: str):
url = f"https://api.twitter.com/2/users/by/username/{username}?user.fields=created_at,name,description,public_metrics,profile_image_url"

async with aiohttp.ClientSession(raise_for_status=True) as session:
async with session.get(url, headers=self.headers) as resp:
data = await resp.json()

return data, "errors" in data

async def get_latest_tweet(self, tid: str):
url = f"https://api.twitter.com/2/users/{tid}/tweets?tweet.fields=public_metrics,created_at,text"

async with aiohttp.ClientSession(raise_for_status=True) as session:
async with session.get(url, headers=self.headers) as resp:
data = await resp.json()

last_tweet = data["meta"]["newest_id"]
tweet = [x for x in data["data"] if x["id"] == last_tweet]

return tweet[0]["text"], tweet[0]["public_metrics"], tweet[0]["created_at"]



def setup(bot):
bot.add_cog(Twitter(bot))
Binary file added Suhail/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions Suhail/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os
import discord
from discord.ext import commands
from dotenv import load_dotenv

load_dotenv()

class Bot(commands.Bot):

def __init__(self, command_prefix):
super().__init__(command_prefix)
self.load_extension("cogs.hi")
self.load_extension("cogs.clear")
self.load_extension("cogs.error")
self.load_extension("cogs.random")
self.load_extension("cogs.twitter")

async def on_ready(self):
print(f"READY! Loaded {self.user}")


bot = Bot(command_prefix="!")

if __name__ == "__main__":
bot.run(os.environ["TOKEN"])
2 changes: 2 additions & 0 deletions Suhail/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
discord.py==1.7.3
python-dotenv
45 changes: 45 additions & 0 deletions Suhail/tests/test_hi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import asyncio
import pytest
import discord
from discord.ext import commands, test as dpytest

from cogs import hi
@pytest.fixture
async def bot(event_loop):

intents = discord.Intents.default()
intents.members = True

b = commands.Bot(command_prefix="!", loop=event_loop, intents=intents)
dpytest.configure(b)
return b

@pytest.fixture(autouse=True)
def hi_cog(bot: commands.Bot):
hi_cog = hi.Hi(bot)
bot.add_cog(hi_cog)
dpytest.configure(bot)
return hi_cog


@pytest.mark.asyncio
async def test_hi():
await dpytest.message("!hi suhail")
assert dpytest.verify().message().content("hello suhail!")

@pytest.mark.asyncio
async def test_logo():
await dpytest.message("!logo")
assert dpytest.verify().message().attachment("logo.png")

@pytest.mark.asyncio
async def test_ping():
await dpytest.message("!ping")
assert dpytest.verify().message().contains().content("Pong!")


@pytest.mark.parametrize("test_input,expected", [("insist establish arm brown understand", "arm\nbrown\nestablish\ninsist\nunderstand"), ("tension issue breakdown claim old", "breakdown\nclaim\nissue\nold\ntension")])
@pytest.mark.asyncio
async def test_sort(test_input, expected):
await dpytest.message(f"!sort {test_input}")
assert dpytest.verify().message().content(expected)