diff --git a/Procfile b/Procfile
new file mode 100644
index 0000000..b96cada
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+worker: python main.py
\ No newline at end of file
diff --git a/README.md b/README.md
index 07e4f04..0629a2d 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,13 @@
+
+
+
+
+
+
+
@@ -22,10 +29,47 @@
🤝 The major features of the bot are
Moderation, Fun, Utility, Games, etc.
- based commands.
🍁 The bot is
user-friendly too, making comfortable for everyone to get familiar with discord bots and stuff.
+
+> Make Sure to ⭐ the Repo if You liked it -- It Helps!
-
+## 📋 Features
+
+⚡️ Open-Source\
+⚡️ Contains Cogs for Easy Management of Code\
+⚡ Open to Contributions\
+⚡ Direct Deployable to Heroku\
+⚡ Actively Maintained\
+⚡ Contains Constant New Features of Discord\
+⚡️ Easy to modify
+
+## 🚀 Contributing
+
+### Step 1: Clone The Repo 💡
+
+Fork the repository and then clone it locally by doing -
+
+```bash
+git clone https://github.com/TheKaushikGoswami/Olympus.git
+```
+
+### Step 2: Build Your Code 🔨
+
+Start your magic by modifying the code and making changes of your own. Then push the commit using -
+
+```bash
+git add .
+git commit -m ""
+git push YOUR_REPO_URL develop
+```
+
+### Step 3: Create a new pull request 🔃
+
+After cloning & setting up the local project you can push the changes to your github fork and make a pull request.
## Authors ✒️
-- [@TheKaushikGoswami](https://github.com/TheKaushikGoswami)
\ No newline at end of file
+- [@TheKaushikGoswami](https://github.com/TheKaushikGoswami)
+------
+
+Made with :heart: in India
\ No newline at end of file
diff --git a/cogs/activities.py b/cogs/activities.py
new file mode 100644
index 0000000..716244b
--- /dev/null
+++ b/cogs/activities.py
@@ -0,0 +1,37 @@
+from discord import slash_command, Option
+from discord.ext import commands
+from discord.ext.commands.errors import MissingPermissions, BotMissingPermissions
+
+class Activities(commands.Cog):
+ def __init__(self, bot):
+ self.bot = bot
+
+ @slash_command()
+ @commands.has_permissions(start_embedded_activities=True)
+ async def activity(self, ctx, activity: Option(str, "Choose the Activity You wanna play in the Voice Channel", choices=["Watch Together", "Poker Night", "Chess in the Park", "Betrayal.io", "Fishington.io", "Letter Tile", "Word Snack", "Doodle Crew", "SpellCast", "Awkword", "Checkers in the Park"], required=True)):
+ """🚀 Let's Have Some Fun Activities Together"""
+
+ try:
+ activities = {"Watch Together":'youtube', "Poker Night":'poker', "Chess in the Park":'chess', "Betrayal.io":'betrayal', "Fishington.io":'fishington', "Letter Tile":'letter-tile', "Word Snack": 'word-snack', "Doodle Crew":'doodle-crew', "SpellCast":'spellcast', "Awkword":'awkword', "Checkers in the Park":'checkers'}
+
+ final_activity = activities.get(activity)
+ if ctx.author.voice == None:
+ await ctx.respond(f"**<:Cross:902943066724388926> You Need To Join a Voice Channel in order to Start An Activity!**", ephemeral=True)
+ else:
+ link = await self.bot.togetherControl.create_link(ctx.author.voice.channel.id, final_activity)
+ await ctx.respond(f"Click the Blue Link!\n{link}")
+ except Exception as e:
+ print(e)
+
+ @activity.error
+ async def activity_error(self, ctx, error):
+ if isinstance(error, ConnectionError):
+ await ctx.respond(f"**<:Cross:902943066724388926> Oops! There was an issue connecting to Discord API!**")
+ elif isinstance(error, MissingPermissions):
+ await ctx.respond(f"**<:Cross:902943066724388926> You need `Start Activities` permission to be able to use this command.**")
+ elif isinstance(error, BotMissingPermissions):
+ await ctx.respond(f"**<:Cross:902943066724388926> I don't have enough permissions to Launch the Activity**")
+
+def setup(bot):
+ bot.add_cog(Activities(bot))
+ print("Activities Cog is Loaded\n------")
\ No newline at end of file
diff --git a/cogs/api_cmd.py b/cogs/api_cmd.py
index 2e41fb3..cafe9d0 100644
--- a/cogs/api_cmd.py
+++ b/cogs/api_cmd.py
@@ -1,4 +1,3 @@
-from datetime import datetime
import discord
from discord.ext import commands
import io
@@ -6,7 +5,6 @@
from discord.commands.commands import Option, slash_command
from discord.ext import commands
import aiohttp
-from discord.ext.commands.errors import MissingPermissions
import requests
class Api(commands.Cog):
diff --git a/cogs/fun.py b/cogs/fun.py
index b757e1e..1f55cc4 100644
--- a/cogs/fun.py
+++ b/cogs/fun.py
@@ -562,7 +562,6 @@ async def snap(self, ctx, member: Option(discord.Member, "Choose the Member", re
# setup COMMAND
-
def setup(bot):
bot.add_cog(Fun(bot))
print("Fun Cog is Loaded\n------")
diff --git a/cogs/lavalink.py b/cogs/lavalink.py
deleted file mode 100644
index c16aa78..0000000
--- a/cogs/lavalink.py
+++ /dev/null
@@ -1,239 +0,0 @@
-import re
-import discord
-import lavalink
-from discord.ext import commands
-
-url_rx = re.compile(r'https?://(?:www\.)?.+')
-
-
-class LavalinkVoiceClient(discord.VoiceClient):
- """
- This is the preferred way to handle external voice sending
- This client will be created via a cls in the connect method of the channel
- see the following documentation:
- https://discordpy.readthedocs.io/en/latest/api.html#voiceprotocol
- """
-
- def __init__(self, client: discord.Client, channel: discord.abc.Connectable):
- self.client = client
- self.channel = channel
- # ensure there exists a client already
- if hasattr(self.client, 'lavalink'):
- self.lavalink = self.client.lavalink
- else:
- self.client.lavalink = lavalink.Client(client.user.id)
- self.client.lavalink.add_node(
- 'localhost',
- 2333,
- 'youshallnotpass',
- 'us',
- 'default-node')
- self.lavalink = self.client.lavalink
-
- async def on_voice_server_update(self, data):
- # the data needs to be transformed before being handed down to
- # voice_update_handler
- lavalink_data = {
- 't': 'VOICE_SERVER_UPDATE',
- 'd': data
- }
- await self.lavalink.voice_update_handler(lavalink_data)
-
- async def on_voice_state_update(self, data):
- # the data needs to be transformed before being handed down to
- # voice_update_handler
- lavalink_data = {
- 't': 'VOICE_STATE_UPDATE',
- 'd': data
- }
- await self.lavalink.voice_update_handler(lavalink_data)
-
- async def connect(self, *, timeout: float, reconnect: bool) -> None:
- """
- Connect the bot to the voice channel and create a player_manager
- if it doesn't exist yet.
- """
- # ensure there is a player_manager when creating a new voice_client
- self.lavalink.player_manager.create(guild_id=self.channel.guild.id)
- await self.channel.guild.change_voice_state(channel=self.channel)
-
- async def disconnect(self, *, force: bool) -> None:
- """
- Handles the disconnect.
- Cleans up running player and leaves the voice client.
- """
- player = self.lavalink.player_manager.get(self.channel.guild.id)
-
- # no need to disconnect if we are not connected
- if not force and not player.is_connected:
- return
-
- # None means disconnect
- await self.channel.guild.change_voice_state(channel=None)
-
- # update the channel_id of the player to None
- # this must be done because the on_voice_state_update that
- # would set channel_id to None doesn't get dispatched after the
- # disconnect
- player.channel_id = None
- self.cleanup()
-
-
-class Music(commands.Cog):
- def __init__(self, bot):
- self.bot = bot
-
- if not hasattr(bot, 'lavalink'): # This ensures the client isn't overwritten during cog reloads.
- bot.lavalink = lavalink.Client(bot.user.id)
- bot.lavalink.add_node('127.0.0.1', 2333, 'youshallnotpass', 'eu', 'default-node') # Host, Port, Password, Region, Name
-
- lavalink.add_event_hook(self.track_hook)
-
- def cog_unload(self):
- """ Cog unload handler. This removes any event hooks that were registered. """
- self.bot.lavalink._event_hooks.clear()
-
- async def cog_before_invoke(self, ctx):
- """ Command before-invoke handler. """
- guild_check = ctx.guild is not None
- # This is essentially the same as `@commands.guild_only()`
- # except it saves us repeating ourselves (and also a few lines).
-
- if guild_check:
- await self.ensure_voice(ctx)
- # Ensure that the bot and command author share a mutual voicechannel.
-
- return guild_check
-
- async def cog_command_error(self, ctx, error):
- if isinstance(error, commands.CommandInvokeError):
- await ctx.send(error.original)
- # The above handles errors thrown in this cog and shows them to the user.
- # This shouldn't be a problem as the only errors thrown in this cog are from `ensure_voice`
- # which contain a reason string, such as "Join a voicechannel" etc. You can modify the above
- # if you want to do things differently.
-
- async def ensure_voice(self, ctx):
- """ This check ensures that the bot and command author are in the same voicechannel. """
- player = self.bot.lavalink.player_manager.create(ctx.guild.id, endpoint=str(ctx.guild.region))
- # Create returns a player if one exists, otherwise creates.
- # This line is important because it ensures that a player always exists for a guild.
-
- # Most people might consider this a waste of resources for guilds that aren't playing, but this is
- # the easiest and simplest way of ensuring players are created.
-
- # These are commands that require the bot to join a voicechannel (i.e. initiating playback).
- # Commands such as volume/skip etc don't require the bot to be in a voicechannel so don't need listing here.
- should_connect = ctx.command.name in ('play',)
-
- if not ctx.author.voice or not ctx.author.voice.channel:
- # Our cog_command_error handler catches this and sends it to the voicechannel.
- # Exceptions allow us to "short-circuit" command invocation via checks so the
- # execution state of the command goes no further.
- raise commands.CommandInvokeError('Join a voicechannel first.')
-
- if not player.is_connected:
- if not should_connect:
- raise commands.CommandInvokeError('Not connected.')
-
- permissions = ctx.author.voice.channel.permissions_for(ctx.me)
-
- if not permissions.connect or not permissions.speak: # Check user limit too?
- raise commands.CommandInvokeError('I need the `CONNECT` and `SPEAK` permissions.')
-
- player.store('channel', ctx.channel.id)
- await ctx.author.voice.channel.connect(cls=LavalinkVoiceClient)
- else:
- if int(player.channel_id) != ctx.author.voice.channel.id:
- raise commands.CommandInvokeError('You need to be in my voicechannel.')
-
- async def track_hook(self, event):
- if isinstance(event, lavalink.events.QueueEndEvent):
- # When this track_hook receives a "QueueEndEvent" from lavalink.py
- # it indicates that there are no tracks left in the player's queue.
- # To save on resources, we can tell the bot to disconnect from the voicechannel.
- guild_id = int(event.player.guild_id)
- guild = self.bot.get_guild(guild_id)
- await guild.voice_client.disconnect(force=True)
-
- @commands.command(aliases=['p'])
- async def play(self, ctx, *, query: str):
- """ Searches and plays a song from a given query. """
- # Get the player for this guild from cache.
- player = self.bot.lavalink.player_manager.get(ctx.guild.id)
- # Remove leading and trailing <>. <> may be used to suppress embedding links in Discord.
- query = query.strip('<>')
-
- # Check if the user input might be a URL. If it isn't, we can Lavalink do a YouTube search for it instead.
- # SoundCloud searching is possible by prefixing "scsearch:" instead.
- if not url_rx.match(query):
- query = f'ytsearch:{query}'
-
- # Get the results for the query from Lavalink.
- results = await player.node.get_tracks(query)
-
- # Results could be None if Lavalink returns an invalid response (non-JSON/non-200 (OK)).
- # ALternatively, resullts['tracks'] could be an empty array if the query yielded no tracks.
- if not results or not results['tracks']:
- return await ctx.send('Nothing found!')
-
- embed = discord.Embed(color=discord.Color.blurple())
-
- # Valid loadTypes are:
- # TRACK_LOADED - single video/direct URL)
- # PLAYLIST_LOADED - direct URL to playlist)
- # SEARCH_RESULT - query prefixed with either ytsearch: or scsearch:.
- # NO_MATCHES - query yielded no results
- # LOAD_FAILED - most likely, the video encountered an exception during loading.
- if results['loadType'] == 'PLAYLIST_LOADED':
- tracks = results['tracks']
-
- for track in tracks:
- # Add all of the tracks from the playlist to the queue.
- player.add(requester=ctx.author.id, track=track)
-
- embed.title = 'Playlist Enqueued!'
- embed.description = f'{results["playlistInfo"]["name"]} - {len(tracks)} tracks'
- else:
- track = results['tracks'][0]
- embed.title = 'Track Enqueued'
- embed.description = f'[{track["info"]["title"]}]({track["info"]["uri"]})'
-
- # You can attach additional information to audiotracks through kwargs, however this involves
- # constructing the AudioTrack class yourself.
- track = lavalink.models.AudioTrack(track, ctx.author.id, recommended=True)
- player.add(requester=ctx.author.id, track=track)
-
- await ctx.send(embed=embed)
-
- # We don't want to call .play() if the player is playing as that will effectively skip
- # the current track.
- if not player.is_playing:
- await player.play()
-
- @commands.command(aliases=['dc'])
- async def disconnect(self, ctx):
- """ Disconnects the player from the voice channel and clears its queue. """
- player = self.bot.lavalink.player_manager.get(ctx.guild.id)
-
- if not player.is_connected:
- # We can't disconnect, if we're not connected.
- return await ctx.send('Not connected.')
-
- if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)):
- # Abuse prevention. Users not in voice channels, or not in the same voice channel as the bot
- # may not disconnect the bot.
- return await ctx.send('You\'re not in my voicechannel!')
-
- # Clear the queue to ensure old tracks don't start playing
- # when someone else queues something.
- player.queue.clear()
- # Stop the current track so Lavalink consumes less resources.
- await player.stop()
- # Disconnect from the voice channel.
- await ctx.voice_client.disconnect(force=True)
- await ctx.send('*⃣ | Disconnected.')
-
-
-def setup(bot):
- bot.add_cog(Music(bot))
\ No newline at end of file
diff --git a/cogs/mod.py b/cogs/mod.py
index d574950..ccceda5 100644
--- a/cogs/mod.py
+++ b/cogs/mod.py
@@ -1,10 +1,10 @@
import discord
-from discord.commands.commands import Option, message_command
+from discord.commands.commands import Option
from discord.commands.errors import ApplicationCommandInvokeError
-from discord.errors import Forbidden, HTTPException, NotFound
+from discord.errors import NotFound
from discord.ext import commands
from discord.commands import slash_command
-from discord.ext.commands.errors import MissingPermissions, NotOwner
+from discord.ext.commands.errors import MissingPermissions
import asyncio
class Mod(commands.Cog):
diff --git a/cogs/olympus.py b/cogs/olympus.py
index ef4d759..4a05bdf 100644
--- a/cogs/olympus.py
+++ b/cogs/olympus.py
@@ -1,12 +1,9 @@
import discord, datetime, time
-from discord.commands.commands import command, slash_command
+from discord.commands.commands import slash_command
from discord.ext import commands
-import sys
import datetime
-import random
import platform
import time
-from discord.ext.commands import bot
import discord.utils
start_time = time.time()
diff --git a/requirements.txt b/requirements.txt
index 8e9824b..73dacb8 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,6 +3,7 @@ ago == 0.0.93
aiohttp == 3.7.4.post0
disputils == 0.2.0
requests == 2.25.1
+discord-together
# For Installing py-cord use:
git+https://github.com/Pycord-Development/pycord