Skip to content

Base Plugin

Just Call Me Koko edited this page May 10, 2022 · 1 revision

Base Plugin

To create a plugin, there are a list of requirements that must be met in order for the plugin to be imported properly into the main app.

Environment Requirements

  • The plugin must follow the naming convention plugin_<name of plugin>.py
  • The plugin filename must use _ in place of spaces
  • The plugin class must follow a similar naming convention as the filename except camel case instead of snake case
    • plugin_test_plugin.py > class TestPlugin():
  • The plugin must be placed in the plugin directory

Required Class Data Structure

Plugins must contain the following data members and member functions

Member Description
conf_path The path where config files are stored
guild_confs A list of the different guild configurations for this plugin
configutils Responsible for managing plugin configurations
name The name of the plugin as well as the command syntax
desc The description/purpose of the command
synt The syntax/usage including available arguments of the command
looping Boolean to allow the plugin to track whether or not it is currently looping
group The discord role required in order to run the plugin
admin Boolean specifying whether or not discord admin privs are required to run the plugin
cheer Needs to be deprecated
cat Category of the plugin
is_service Boolean to define whether or not the plugin is a service
client Stores the client object of the discord bot itself
def __init__(self, client = None): Well...you know
def getArgs(self, message): Returns space delimited arguments from user message
def generatePluginConfig(self, file_name): Generated plugin configuration when bot joins new guild
def checkCat(self, check_cat): Needs to be deprecated
def checkBits(self, bits): Needs to be deprecated
async def runCheer(self, user, amount): Needs to be deprecated
async def run(self, message, obj_list): The main logic of the plugin
async def stop(self, message): If the plugin is a service, this is called to stop it

Example of a basic plugin

This assumes the filename of the plugin is plugin_template.py

import os
import sys
import json
import discord
from dotenv import load_dotenv
from discord.ext.tasks import loop
from requests import get

sys.path.append(os.path.abspath('utils'))

from utils.config_utils import ConfigUtils

class Template():
	# Required for all plugins
	conf_path = os.path.join(os.path.dirname(__file__), 'configs')

	guild_confs = []

	configutils = None

	name = '!template'

	desc = 'This does nothing. Developer only'

	synt = '!template [config|get <config>|set <config> <value>|add/remove <config> <value>]'

	is_service = False

	client = None

	looping = False

	full_conf_file = None

	default_config = {}
	default_config['protected'] = {}
	default_config['protected']['name'] = __file__
	default_config['protected']['guild'] = None
	default_config['standard_groups'] = {}
	default_config['standard_groups']['value'] = []
	default_config['standard_groups']['description'] = "Authorized groups to use this command"
	default_config['admin_groups'] = {}
	default_config['admin_groups']['value'] = []
	default_config['admin_groups']['description'] = "Authorized groups to use admin functions of this command"
	default_config['blacklisted'] = {}
	default_config['blacklisted']['value'] = []
	default_config['blacklisted']['description'] = "Groups explicitly denied access to this command"
	default_config['post_channel'] = {}
	default_config['post_channel']['value'] = ""
	default_config['post_channel']['description'] = "Desitination channel to post messages from this plugin"

	# Server configurable

	group = '@everyone'

	admin = False
	
	cheer = -1
	
	cat = 'admin'
	
	# This must be your constructor (at least)
	def __init__(self, client = None):
		self.client = client
		self.configutils = ConfigUtils()

		# Load configuration if it exists
		self.guild_confs = self.configutils.loadConfig(self.conf_path, self.default_config, __file__)


		print('\n\nConfigs Loaded:')
		for config in self.guild_confs:
			print('\t' + config['protected']['name'] + ': ' + config['protected']['guild'])

	# This exact method is required
	def getArgs(self, message):
		cmd = str(message.content)
		seg = str(message.content).split(' ')

		if len(seg) > 1:
			return seg
		else:
			return None

	# This exact method is required
	def generatePluginConfig(self, file_name):
		for new_conf in self.configutils.generateConfig(self.conf_path, self.default_config, file_name, __file__):
			self.guild_confs.append(new_conf)

	# This exact method is required
	def checkCat(self, check_cat):
		if self.cat == check_cat:
			return True
		else:
			return False
	
	# This exact method is required
	def checkBits(self, bits):
		return False
	
	# This exact method is required
	async def runCheer(self, user, amount):
		return True

	async def run(self, message, obj_list):
		### Begin required code
		# Permissions check
		if not self.configutils.hasPerms(message, False, self.guild_confs):
			await message.channel.send(message.author.mention + ' Permission denied')
			return False

		# Parse args
		arg = self.getArgs(message)

		# Config set/get check
		if arg != None:
			if await self.configutils.runConfig(message, arg, self.guild_confs, self.conf_path):
				return True

		#### END REQUIRED CODE

		# Do Specific Plugin Stuff

		return True

	# This exact method is required
	async def stop(self, message):
		self.looping = False