From 4a84ca0a6536f0aac03436dc0d4f501e769fd6de Mon Sep 17 00:00:00 2001 From: Slushie Date: Mon, 19 Jul 2021 13:30:35 +0100 Subject: [PATCH 1/6] Add requirements.txt --- Suhail/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 Suhail/requirements.txt diff --git a/Suhail/requirements.txt b/Suhail/requirements.txt new file mode 100644 index 0000000..7750a0e --- /dev/null +++ b/Suhail/requirements.txt @@ -0,0 +1 @@ +discord.py==1.7.3 \ No newline at end of file From 8e18672760d8664b3fc9b28dcea1cca1885c719b Mon Sep 17 00:00:00 2001 From: Slushie Date: Mon, 19 Jul 2021 13:34:31 +0100 Subject: [PATCH 2/6] Add bot and commands --- Suhail/cogs/clear.py | 16 ++++++++++++++++ Suhail/cogs/error.py | 15 +++++++++++++++ Suhail/cogs/hi.py | 31 +++++++++++++++++++++++++++++++ Suhail/cogs/random.py | 25 +++++++++++++++++++++++++ Suhail/main.py | 15 +++++++++++++++ 5 files changed, 102 insertions(+) create mode 100644 Suhail/cogs/clear.py create mode 100644 Suhail/cogs/error.py create mode 100644 Suhail/cogs/hi.py create mode 100644 Suhail/cogs/random.py create mode 100644 Suhail/main.py diff --git a/Suhail/cogs/clear.py b/Suhail/cogs/clear.py new file mode 100644 index 0000000..26a106f --- /dev/null +++ b/Suhail/cogs/clear.py @@ -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)) \ No newline at end of file diff --git a/Suhail/cogs/error.py b/Suhail/cogs/error.py new file mode 100644 index 0000000..941cb29 --- /dev/null +++ b/Suhail/cogs/error.py @@ -0,0 +1,15 @@ +import discord +from discord.ext import commands + +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") + +def setup(bot): + bot.add_cog(Error(bot)) diff --git a/Suhail/cogs/hi.py b/Suhail/cogs/hi.py new file mode 100644 index 0000000..a7d39a6 --- /dev/null +++ b/Suhail/cogs/hi.py @@ -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)) \ No newline at end of file diff --git a/Suhail/cogs/random.py b/Suhail/cogs/random.py new file mode 100644 index 0000000..b52f275 --- /dev/null +++ b/Suhail/cogs/random.py @@ -0,0 +1,25 @@ +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))) + +def setup(bot): + bot.add_cog(Random(bot)) \ No newline at end of file diff --git a/Suhail/main.py b/Suhail/main.py new file mode 100644 index 0000000..1a817c3 --- /dev/null +++ b/Suhail/main.py @@ -0,0 +1,15 @@ +import config +import discord +from discord.ext import commands + +class Bot(commands.Bot): + async def on_ready(self): + print(f"READY! Loaded {self.user}") + self.load_extension("cogs.hi") + self.load_extension("cogs.clear") + self.load_extension("cogs.error") + self.load_extension("cogs.random") + +bot = Bot(command_prefix="!") + +bot.run(config.TOKEN) \ No newline at end of file From 233dfcce661292fa2cdb2db09605cd88640fc984 Mon Sep 17 00:00:00 2001 From: Slushie Date: Mon, 19 Jul 2021 13:49:18 +0100 Subject: [PATCH 3/6] Made TOKEN into dotenv --- Suhail/main.py | 7 +++++-- Suhail/requirements.txt | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Suhail/main.py b/Suhail/main.py index 1a817c3..7cdb3e9 100644 --- a/Suhail/main.py +++ b/Suhail/main.py @@ -1,6 +1,9 @@ -import config +import os import discord from discord.ext import commands +from dotenv import load_dotenv + +load_dotenv() class Bot(commands.Bot): async def on_ready(self): @@ -12,4 +15,4 @@ async def on_ready(self): bot = Bot(command_prefix="!") -bot.run(config.TOKEN) \ No newline at end of file +bot.run(os.environ["TOKEN"]) \ No newline at end of file diff --git a/Suhail/requirements.txt b/Suhail/requirements.txt index 7750a0e..8dd7936 100644 --- a/Suhail/requirements.txt +++ b/Suhail/requirements.txt @@ -1 +1,2 @@ -discord.py==1.7.3 \ No newline at end of file +discord.py==1.7.3 +python-dotenv \ No newline at end of file From f586ac4bf2af53815c67fee06da151f29f88a682 Mon Sep 17 00:00:00 2001 From: Slushie Date: Mon, 19 Jul 2021 13:49:24 +0100 Subject: [PATCH 4/6] Added cat command --- Suhail/cogs/random.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Suhail/cogs/random.py b/Suhail/cogs/random.py index b52f275..6b56ac9 100644 --- a/Suhail/cogs/random.py +++ b/Suhail/cogs/random.py @@ -1,3 +1,4 @@ +import aiohttp import discord import random from discord.ext import commands @@ -21,5 +22,12 @@ async def roll(self, ctx, count: int): 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)) \ No newline at end of file From 5e7f6e093fa881397d830032631475812113600f Mon Sep 17 00:00:00 2001 From: Slushie Date: Tue, 20 Jul 2021 14:32:44 +0100 Subject: [PATCH 5/6] beginning of tests --- Suhail/logo.png | Bin 0 -> 12036 bytes Suhail/tests/test_hi.py | 45 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 Suhail/logo.png create mode 100644 Suhail/tests/test_hi.py diff --git a/Suhail/logo.png b/Suhail/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bfef4483c46d9c3bae180a4a9a63a388d39569d3 GIT binary patch literal 12036 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 literal 0 HcmV?d00001 diff --git a/Suhail/tests/test_hi.py b/Suhail/tests/test_hi.py new file mode 100644 index 0000000..6f5dbb4 --- /dev/null +++ b/Suhail/tests/test_hi.py @@ -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) From efdd146718c9cdc82b512e58e764b2c04f4b2dff Mon Sep 17 00:00:00 2001 From: Slushie Date: Thu, 22 Jul 2021 15:42:57 +0100 Subject: [PATCH 6/6] Twitter --- Suhail/cogs/error.py | 5 +++ Suhail/cogs/twitter.py | 93 ++++++++++++++++++++++++++++++++++++++++++ Suhail/main.py | 13 ++++-- 3 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 Suhail/cogs/twitter.py diff --git a/Suhail/cogs/error.py b/Suhail/cogs/error.py index 941cb29..7d2a439 100644 --- a/Suhail/cogs/error.py +++ b/Suhail/cogs/error.py @@ -1,5 +1,7 @@ +from inspect import trace import discord from discord.ext import commands +import traceback class Error(commands.Cog): @@ -10,6 +12,9 @@ def __init__(self, bot): 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)) diff --git a/Suhail/cogs/twitter.py b/Suhail/cogs/twitter.py new file mode 100644 index 0000000..ed1f756 --- /dev/null +++ b/Suhail/cogs/twitter.py @@ -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)) \ No newline at end of file diff --git a/Suhail/main.py b/Suhail/main.py index 7cdb3e9..8049e64 100644 --- a/Suhail/main.py +++ b/Suhail/main.py @@ -6,13 +6,20 @@ load_dotenv() class Bot(commands.Bot): - async def on_ready(self): - print(f"READY! Loaded {self.user}") + + 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="!") -bot.run(os.environ["TOKEN"]) \ No newline at end of file +if __name__ == "__main__": + bot.run(os.environ["TOKEN"]) \ No newline at end of file