├── .env ├── requirements.txt ├── data ├── suggestions.db └── create.py ├── README.md ├── util ├── functions.py └── database.py ├── commands └── suggest.py ├── bot.py └── view.py /.env: -------------------------------------------------------------------------------- 1 | DISCORD_LOGIN_TOKEN= -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | py-cord 2 | python-dotenv 3 | aiosqlite 4 | -------------------------------------------------------------------------------- /data/suggestions.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/noemtdev/bot-template/HEAD/data/suggestions.db -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bot-template 2 | 3 | This is a Python Discord Bot Template using the **py-cord** library. It comes with a suggestion system. 4 | (Make sure to set **self.suggestions_channel** in **bot.py** to your actual channel) 5 | -------------------------------------------------------------------------------- /util/functions.py: -------------------------------------------------------------------------------- 1 | import os 2 | import dotenv 3 | 4 | class BotStuff: 5 | def __init__(self): 6 | dotenv.load_dotenv() 7 | 8 | def load_token(self): 9 | return os.getenv('DISCORD_LOGIN_TOKEN') 10 | 11 | -------------------------------------------------------------------------------- /data/create.py: -------------------------------------------------------------------------------- 1 | import aiosqlite 2 | import asyncio 3 | 4 | async def main(): 5 | async with aiosqlite.connect("suggestions.db") as db: 6 | async with db.execute("CREATE TABLE IF NOT EXIST views (message_id INTEGER, voted TEXT)") as create: 7 | await db.commit() 8 | 9 | asyncio.run(main()) -------------------------------------------------------------------------------- /util/database.py: -------------------------------------------------------------------------------- 1 | import aiosqlite 2 | from discord.ext import tasks 3 | 4 | class Database: 5 | def __init__(self, bot, path): 6 | self.bot = bot 7 | self.path = path 8 | self.init.start() 9 | 10 | @tasks.loop(count=1) 11 | async def init(self): 12 | self.db = await aiosqlite.connect(self.path) 13 | 14 | async def close(self): 15 | await self.db.commit() 16 | await self.db.close() 17 | 18 | async def execute(self, query, *args): 19 | return await self.db.execute(query, *args) 20 | 21 | async def fetchone(self, cursor): 22 | return await cursor.fetchone() 23 | 24 | async def fetchall(self, cursor): 25 | return await cursor.fetchall() 26 | 27 | async def commit(self): 28 | await self.db.commit() 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /commands/suggest.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord import Option 3 | from discord.ext import commands 4 | from view import SuggestionView 5 | import datetime 6 | 7 | 8 | class Suggest(commands.Cog): 9 | def __init__(self, bot): 10 | self.bot = bot 11 | 12 | @commands.slash_command( 13 | name="suggest", 14 | description="Suggests Something", 15 | ) 16 | async def suggest(self, ctx, suggestion: Option(str, "Explain your suggestion as well as possible.", required=True)): 17 | 18 | embed = discord.Embed( 19 | title=f"Suggestion by {ctx.author.name}", 20 | description=suggestion, 21 | color=discord.Color.blurple() 22 | ) 23 | embed.set_author(name=str(ctx.author), icon_url=ctx.author.avatar.url) 24 | embed.timestamp = datetime.datetime.utcnow() 25 | 26 | ms = await self.bot.get_channel(self.bot.suggestions_channel).send(embed=embed) 27 | await ms.edit(view=SuggestionView(self.bot, message_id=ms.id)) 28 | 29 | await self.bot.suggestion_database.execute("INSERT INTO views (message_id, voted) VALUES (?, ?)", (ms.id, str({"up": [], "down": []}))) 30 | await self.bot.suggestion_database.commit() 31 | 32 | return await ctx.respond("Your suggestion has been sent!", ephemeral=True) 33 | 34 | def setup(bot): 35 | bot.add_cog(Suggest(bot)) 36 | -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | from abc import ABC 2 | 3 | import discord 4 | from discord.ext import commands 5 | 6 | import os 7 | import json 8 | 9 | from util.functions import BotStuff 10 | from util.database import Database 11 | from view import SuggestionView 12 | 13 | class Bot(commands.Bot, ABC): 14 | 15 | def __init__(self, *args, **kwargs): 16 | super().__init__(*args, **kwargs) 17 | 18 | self.botStuff = BotStuff() 19 | self.token = self.botStuff.load_token() 20 | self.suggestions_channel = 1066577547116163102 21 | self.command_prefix = '!' 22 | self.remove_command('help') 23 | self.embed_color = discord.Color.blurple() 24 | self.suggestion_database = Database(self, 'data/suggestions.db') 25 | self.owner_id = 352793093105254402 26 | 27 | async def on_ready(self): 28 | await self.load_views() 29 | 30 | def load_commands(self): 31 | for filename in os.listdir('./commands'): 32 | if filename.endswith('.py'): 33 | self.load_extension(f'commands.{filename[:-3]}') 34 | 35 | def run(self): 36 | self.load_commands() 37 | super().run(self.token) 38 | 39 | async def load_views(self): 40 | cur = await bot.suggestion_database.execute("SELECT * FROM views") 41 | rows = await bot.suggestion_database.fetchall(cur) 42 | 43 | for row in rows: 44 | voted = json.loads(row[1].replace("'", '"')) 45 | bot.add_view(SuggestionView(self._bot, row[0], voted)) 46 | 47 | 48 | intents = discord.Intents.default() 49 | bot = Bot(intents=intents) 50 | 51 | bot.run() 52 | -------------------------------------------------------------------------------- /view.py: -------------------------------------------------------------------------------- 1 | from discord.ui import View, button 2 | import discord 3 | 4 | class SuggestionView(View): 5 | def __init__(self, bot, message_id: int, voted: dict=None): 6 | super().__init__() 7 | 8 | self.timeout = None 9 | 10 | if voted is None: 11 | voted = {"up": [], "down": []} 12 | self.upvotes = 0 13 | self.downvotes = 0 14 | self.difference = 0 15 | else: 16 | self.upvotes = len(voted["up"]) 17 | self.downvotes = len(voted["down"]) 18 | self.difference = self.upvotes - self.downvotes 19 | 20 | self.voted: dict = voted 21 | self.message_id = message_id 22 | self.bot = bot 23 | 24 | async def edit_embed_color(self, message, embed, view, interaction): 25 | if self.difference < 0: 26 | embed.color = discord.Color.red() 27 | 28 | elif self.difference > 0: 29 | embed.color = discord.Color.green() 30 | 31 | else: 32 | embed.color = discord.Color.blurple() 33 | 34 | await message.edit(embed=embed, view=view) 35 | return await interaction.response.defer() 36 | 37 | 38 | 39 | 40 | @button(label="0", style=discord.ButtonStyle.blurple, emoji="👍", custom_id="upvote") 41 | async def upvote(self, button: discord.ui.Button, interaction: discord.Interaction): 42 | if interaction.user.id in self.voted["up"]: 43 | 44 | self.upvotes -= 1 45 | self.difference -= 1 46 | 47 | self.voted["up"].remove(interaction.user.id) 48 | 49 | button.label = str(self.upvotes) 50 | self.children[1].label = str(self.difference) 51 | self.children[2].label = str(self.downvotes) 52 | 53 | if self.difference < 0: 54 | button.style = discord.ButtonStyle.red 55 | self.children[2].style = discord.ButtonStyle.green 56 | 57 | elif self.difference > 0: 58 | button.style = discord.ButtonStyle.green 59 | self.children[2].style = discord.ButtonStyle.red 60 | 61 | else: 62 | button.style = discord.ButtonStyle.blurple 63 | self.children[2].style = discord.ButtonStyle.blurple 64 | 65 | elif interaction.user.id in self.voted["down"]: 66 | self.downvotes -= 1 67 | self.difference += 2 68 | self.upvotes += 1 69 | 70 | self.voted["down"].remove(interaction.user.id) 71 | self.voted["up"].append(interaction.user.id) 72 | 73 | button.label = str(self.upvotes) 74 | self.children[1].label = str(self.difference) 75 | self.children[2].label = str(self.downvotes) 76 | 77 | if self.difference < 0: 78 | button.style = discord.ButtonStyle.red 79 | self.children[2].style = discord.ButtonStyle.green 80 | 81 | elif self.difference > 0: 82 | button.style = discord.ButtonStyle.green 83 | self.children[2].style = discord.ButtonStyle.red 84 | 85 | else: 86 | button.style = discord.ButtonStyle.blurple 87 | self.children[2].style = discord.ButtonStyle.blurple 88 | 89 | else: 90 | self.upvotes += 1 91 | self.difference += 1 92 | 93 | self.voted["up"].append(interaction.user.id) 94 | 95 | button.label = str(self.upvotes) 96 | self.children[1].label = str(self.difference) 97 | self.children[2].label = str(self.downvotes) 98 | 99 | if self.difference < 0: 100 | button.style = discord.ButtonStyle.red 101 | self.children[2].style = discord.ButtonStyle.green 102 | 103 | elif self.difference > 0: 104 | button.style = discord.ButtonStyle.green 105 | self.children[2].style = discord.ButtonStyle.red 106 | 107 | else: 108 | button.style = discord.ButtonStyle.blurple 109 | self.children[2].style = discord.ButtonStyle.blurple 110 | 111 | await self.edit_embed_color(interaction.message, interaction.message.embeds[0], self, interaction) 112 | 113 | await self.bot.suggestion_database.execute("UPDATE views SET voted = ? WHERE message_id = ?", (str(self.voted), self.message_id)) 114 | await self.bot.suggestion_database.commit() 115 | 116 | @button(label="0", style=discord.ButtonStyle.blurple, disabled=True, custom_id="diff") 117 | async def diff(self, button: discord.ui.Button, interaction: discord.Interaction): 118 | pass 119 | 120 | @button(label="0", style=discord.ButtonStyle.blurple, emoji="👎", custom_id="downvote") 121 | async def downvote(self, button: discord.ui.Button, interaction: discord.Interaction): 122 | 123 | if interaction.user.id in self.voted["down"]: 124 | 125 | self.downvotes -= 1 126 | self.difference += 1 127 | 128 | self.voted["down"].remove(interaction.user.id) 129 | 130 | button.label = str(self.downvotes) 131 | self.children[1].label = str(self.difference) 132 | self.children[0].label = str(self.upvotes) 133 | 134 | if self.difference < 0: 135 | button.style = discord.ButtonStyle.red 136 | self.children[0].style = discord.ButtonStyle.green 137 | 138 | elif self.difference > 0: 139 | button.style = discord.ButtonStyle.green 140 | self.children[0].style = discord.ButtonStyle.red 141 | 142 | else: 143 | button.style = discord.ButtonStyle.blurple 144 | self.children[0].style = discord.ButtonStyle.blurple 145 | 146 | elif interaction.user.id in self.voted["up"]: 147 | self.upvotes -= 1 148 | self.difference -= 2 149 | self.downvotes += 1 150 | 151 | self.voted["up"].remove(interaction.user.id) 152 | self.voted["down"].append(interaction.user.id) 153 | 154 | self.children[1].label = str(self.difference) 155 | self.children[0].label = str(self.upvotes) 156 | 157 | button.label = str(self.downvotes) 158 | 159 | if self.difference < 0: 160 | button.style = discord.ButtonStyle.green 161 | self.children[0].style = discord.ButtonStyle.red 162 | 163 | elif self.difference > 0: 164 | button.style = discord.ButtonStyle.red 165 | self.children[0].style = discord.ButtonStyle.green 166 | 167 | else: 168 | button.style = discord.ButtonStyle.blurple 169 | self.children[0].style = discord.ButtonStyle.blurple 170 | 171 | else: 172 | self.downvotes += 1 173 | self.difference -= 1 174 | 175 | self.voted["down"].append(interaction.user.id) 176 | 177 | button.label = str(self.downvotes) 178 | self.children[1].label = str(self.difference) 179 | self.children[0].label = str(self.upvotes) 180 | 181 | if self.difference < 0: 182 | button.style = discord.ButtonStyle.green 183 | self.children[0].style = discord.ButtonStyle.red 184 | 185 | elif self.difference > 0: 186 | button.style = discord.ButtonStyle.red 187 | self.children[0].style = discord.ButtonStyle.green 188 | 189 | else: 190 | button.style = discord.ButtonStyle.blurple 191 | self.children[0].style = discord.ButtonStyle.blurple 192 | 193 | 194 | await self.edit_embed_color(interaction.message, interaction.message.embeds[0], self, interaction) 195 | 196 | await self.bot.suggestion_database.execute("UPDATE views SET voted = ? WHERE message_id = ?", (str(self.voted), self.message_id)) 197 | await self.bot.suggestion_database.commit() 198 | --------------------------------------------------------------------------------