Commit 345952a2 authored by Joseph's avatar Joseph
Browse files

current_version_of_community_bot

yes
parent da1b618c
# -*- coding: utf-8 -*-
"""
Created on Sat Sep 5 14:09:29 2020
@author: josep
"""
import discord
import smtplib, ssl
from datetime import datetime
from random import random
from asyncio import create_task, sleep, run
from PublicChannel import PubChanSuite, PublicChan
from ClubChannel import ClubSuite, Club
from restrictedchannel import RestrictChan, RestrictChanSuite
from handles import User, ECMember, ECStudent, ECFaculty, Organizer, Convener, Admin, SuperAdmin
def get_member_by_discord_name(guild, discord_name):
for member in guild.members:
if member.name + "#" + member.discriminator == discord_name:
return member
return False
def is_auth(channel, auth_channel_name):
print(channel.name)
return channel.name == auth_channel_name
#for channel in guild.text_channels:
# if channel.name == auth_channel_name:
# return channel
#return False
auth_channel = 'auth'
domain_dest = '@earlham.edu'
send_account_email='earlhamhackerscontrol@gmail.com'
account_password = 'Z1iCriDx$16yBjf1!2#8JH'
student_role_name = 'ECStudent'
faculty_role_name = 'ECFaculty'
clubs = []
users = []
client = discord.Client()
async def make_new_member(member):
new_member = User(member.guild, member)
await new_member._init(authChannel=auth_channel)
users.append(new_member)
return new_member
@client.event
async def on_member_join(member):
await make_new_member(member)
@client.event
async def on_message(message):
if message.author == client.user:
return
#await message.channel.send('received', delete_after=3)
# Is it a command? if it's not a command, ignore. Otherwise, proceed.
content = message.content.lower()
if content.startswith('!'):
'''
Check if channel is server's auth channel. If so, allow auth commands.
'''
try:
maybe_auth = is_auth(message.channel, auth_channel)#''' This will break the program later. message.channel can be a DM channel. find a way to make it so that that wont break the channel'''
except:
print('could not find auth channel')
return
print('got auth channel: ' + str(maybe_auth))
if maybe_auth:
# Get the user to do auth stuff with
auth_user = None
for user in users:
if user._member.id == message.author.id:
auth_user = user
break
if auth_user == None:
print("Failed to find user: " + message.author.name + ". Making new one")
auth_user = await make_new_member(get_member_by_discord_name(message.channel.guild, message.author.name + "#" + message.author.discriminator))
'''
AUTH COMMANDS GO HERE
'''
print('made it to auth commands')
#killer = create_task(kill_after_n(3, message)) # messages in this channel expire after 3 seconds
if content.startswith('!auth'): # this allows users to put in their codes
if await auth_user.authenticate(content[len('!auth '):].upper(), student_role_name, faculty_role_name) == True:
users.remove(auth_user)
await message.channel.send('Authenticatoin succeeded... Moving to Full Discord', delete_after = 3)
else:
await message.channel.send('Authentication failed... ' + content[len('!auth '):] + ' is not the correct auth code', delete_after = 3)
else: #anything else is ![prefix] which files an email attempt
print('sent email to ' + content[len('!'):])
auth_user.send_auth_email_to_addr(content[len('!'):], domain_dest,send_account_email, account_password)
await message.channel.send('Send auth code to: ' + content[len('!'):], delete_after = 3)
#run(killer)
await message.delete(delay=3)
return
'''
Check if the channel mentioned is a cli for a pubchan. If so, perform pubchan commands.
'''
try:
is_admin = message.channel.name == 'admin'
#maybe_pubchan = PubChanSuite.is_cli(PubChanSuite.get_all_pubchans(message.channel.guild, message.channel))
except:
is_admin = False
if is_admin:
'''
moderator commands go here
'''
# Add, remove hangout spaces
if content.startswith('!addpubchan'):
clubName = content[len('!addpubchan '):].upper()
clubs = list(PubChanSuite.get_all_pubchans(message.channel.guild))
# make sure we're not making a duplicate club
for i in range(len(clubs)):
clubs[i] = clubs[i].name
if clubName in clubs:
await message.channel.send('Sorry, that pubchan name is already taken. try a different one?', delete_after = 5)
return
# and make the club if not a duplicate
newClub = PublicChan(message.guild, message.author, clubName)
await newClub._init()
return
'''
Restricted Channel commands go here
'''
if content.startswith('!addrestrictedchan'):
clubName = content[len('!addrestrictedchan '):].upper()
clubs = list(RestrictChanSuite.get_all_restrictchans(message.channel.guild))
# make sure we're not making a duplicate club
for i in range(len(clubs)):
clubs[i] = clubs[i].name
if clubName in clubs:
await message.channel.send('Sorry, that restrictedchannel name is already taken. try a different one?', delete_after = 5)
return
# and make the club if not a duplicate
newClub = RestrictChan(message.guild, message.author, clubName)
await newClub._init()
return
'''
Check if the channel mentioned is a cli for a club. if so, perform club commands.
'''
# try catch around this boy
if await ClubSuite.processes_inc_command(message):
await message.channel.send('Succeeded...', delete_after=3)
return
'''
GENERAL COMMANDS GO HERE
'''
if content.startswith('!makeclub'):
clubName = content[len('!makeclub '):].upper()
clubs = list(ClubSuite.get_all_clubs(message.channel.guild))
# make sure we're not making a duplicate club
for i in range(len(clubs)):
clubs[i] = clubs[i].name.lower()
if clubName in clubs:
await message.channel.send('Sorry, that clubname is already taken. try a different one?', delete_after = 5)
return
# and make the club if not a duplicate
newClub = Club(message.guild, message.author, clubName)
await newClub._init()
return
elif content.startswith('!joinclub'):
target = ('c-' + content[len('!joinclub '):]).upper()
print('registered joinclub for' + target)
target_club = ClubSuite.get_club(ClubSuite.get_all_clubs(message.channel.guild), target)
await ClubSuite.add_member(target_club, message.author)
return
# Find club category
# if there is a role called category [member], add the person to the role]
elif content.startswith('!leaveclub'):
target = ('c-' + content[len('!leaveclub '):]).upper()
print('registered leaveclub for' + target)
target_club = ClubSuite.get_club(ClubSuite.get_all_clubs(message.channel.guild), target)
await ClubSuite.kick_member(target_club, message.author)
return
elif content.startswith('!MAKESTUDENT'):
student = ECStudent(get_member_by_discord_name(message.channel.guild, content[len('!MAKESTUDENT '):]))
await student._init(role_name=student_role_name)
return
elif content.startswith('!clublist'):
clubs = ClubSuite.get_all_clubs(message.channel.guild)
send_text = 'The clubs in ' + message.channel.guild.name + ' are: \n\t'
for club in clubs:
send_text += club.name[2:] + '\n\t'
await message.channel.send(send_text)
elif content.startswith('!examples'):
commands = ['!clublist\n\t\t - lists all clubs in ' + message.channel.guild.name,
'!joinclub ECHackers\n\t\t - Joins the ECHackers Club',
'!leaveclub ECHackers\n\t\t - Leaves the ECHackers Club',
'!makeclub JelloLicking\n\t\t - Makes the JelloLicking club',
'!admin\n\t\t - (does nothing now) Opens a channel with you and admins',
'!report person reason\n\t\t - (does nothing now) Sends a report on a person to an admin or club convener.',
'!addtextchannel Problems-with-admin Friend-Houses\n\t\t - Adds the Friend-Houses text channel to Problems-with-admin',
'!removetextchannel Problems-with-admin Friend-Houses\n\t\t - Removes the Friend-Houses text channel from Problems-with-admin (if you made it)',
'!addvoicechannel Problems-with-admin Friend-Houses\n\t\t - Adds the Friend-Houses voice channel to Problems-with-admin',
'!removevoicechannel Problems-with-admin Friend-Houses\n\t\t - Removes the Friend-Houses voice channel from Problems-with-admin (if you made it)',]
send_text = 'Examples of commands ' + message.channel.guild.name + ' are (In order):\n\t'
for command in commands:
send_text += command + '\n\t'
await message.channel.send(send_text)
return
elif content.startswith('!help'):
commands = ['!clublist\n\t\t - Lists all clubs in ' + message.channel.guild.name, '!joinclub Clubname\n\t\t - Joins the club Clubname', '!leaveclub\n\t\t - Leaves a server\'s club',
'!makeclub Clubname\n\t\t - Makes a club with the clubname Clubname','!admin\n\t\t - Opens a channel with you and admins', '!report person reason\n\t\t - Sends a report on a person to an admin or club convener.',
'!addtextchannel The-name-of-the-public-category The-new-channel\'s-name\n\t\t - Adds a new public text channel in a category',
'!removetextchannel The-name-of-the-public-category The-new-channel\'s-name\n\t\t - Removes the public text channel YOU MADE from the category. Doesn\'t work for other people\'s channels',
'!addvoicechannel The-name-of-the-public-category The-new-channel\'s-name\n\t\t - Adds a new public voice channel in a category',
'!removevoicechannel The-name-of-the-public-category The-new-channel\'s-name\n\t\t - Removes the public voice channel YOU MADE from the category. Doesn\'t work for other people\'s channels',]
send_text = 'Commands in ' + message.channel.guild.name + ' are:\n\t'
for command in commands:
send_text += command + '\n\t'
await message.channel.send(send_text)
return
elif content.startswith('!admin'):
await message.channel.send('not yet implemented...')
raise NotImplementedError()
elif content.startswith('!report'):
await message.channel.send('not yet implemented...')
raise NotImplementedError()
# Try to process remaining commands as hangoutspace commands:
if await PubChanSuite.process_commands(message):
await message.channel.send('Succeeded... ', delete_after = 3);return
# or as restricted suite petitions
if await RestrictChanSuite.process_commands(message):
await message.channel.send('Succeeded... ', delete_after = 3)
return
await message.channel.send('Sorry. We didn\'t process your command. Will you check for typos or ask for help and try again?', delete_after=10)
# Check if a message comes in from a CLI channel.
# if in a CLI channel,
# is it an admin channel?
# is it a convener channel?
# is it a ____ channel?
#Process according to context.
# Check if the message is a general command. Process accordingly.
# moderation
# policing
# Down the line:
# In meet & greet lobbies, link to games, shows,
# and movies after 15 min of people talking.
# We NEED to be able to host remote events. Convocation, Speaker events, and more
client.run()
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
Created on Sat Sep 5 14:08:39 2020
@author: josep
"""
import discord
def get_member_by_discord_name(guild, discord_name):
for member in guild.members:
if member.name + "#" + member.discriminator == discord_name:
return member
return False
class Club: # Creates a club category channel with CLUB MEMBER role read and write permissions for club members and CLI access for club convenors
Convenor_abstract_permissions = None
convenor_color = discord.Colour.blue()
Member_abstract_permissions = None
def __init__(self, guild, convener, clubName):
# Make a cli where commands from club conveners here can shape club below.
# Have list of all voice and text channels owned by the club.
# Can only influence voice/text channels owned by this club object.
# Clubs are the only things that can act on the server. Conveners can act
# on club objects.
#Auto give at least one person convener access to the club.
# Needs functionality to give other ECStudents convener roles.
self._guild = guild
self._convener = convener
self._clubName = 'c-' + clubName
async def _init(self):
'''
CREATE & ASSIGN ROLES. (Expandable to include mods, operators, etc.)
'''
# Create convenor role
self._convener_role = await self._guild.create_role(name=self._clubName + " Convener", colour=Club.convenor_color)
# assign convener role
await self._convener.add_roles(self._convener_role)
# Create member role
self._member_role = await self._guild.create_role(name=self._clubName + " Member")
'''
CREATE HOLDER FOR CLUB ASSOCIATED STUDENT ROLES
'''
self._club_roles = [self._convener_role, self._member_role]
'''
CREATE CATEGORY CHANNEL W/ CLUB ASSOCIATED STUDENT ROLES PARTICIPATION PRIVILEDGES
'''
# Create channel
self._category = await self._guild.create_category(name=self._clubName)
for role in self._guild.roles:
await self._category.set_permissions(role, read_messages=False, send_messages=False)
for role in self._club_roles:
await self._category.set_permissions(role, read_messages=True, send_messages=True, connect=True, speak=True)
'''
CREATE CATEGORY DEFAULT TEXT CHANNELS
'''
# Create CLI text channel
self._cli = await self._category.create_text_channel(self._clubName + "-convenor-command-line")
# And make it private to all but conveners
for role in self._guild.roles:
await self._cli.set_permissions(role, read_messages=False, send_messages=False)
await self._cli.edit(topic = 'Only Conveners can use this channel')
await self._cli.set_permissions(self._convener_role, read_messages=True, send_messages=True)
await self._cli.send(ClubSuite.get_help_message(self._cli))
# Only Conveners of this club can post in this channel
# textchannel.set_permissions(rolename, read_messages=True, write_messages=True)
# self._cli_channel_id = None # Cli channel for the club
# Conveners and members of this club can post in this channel. (Use textchannel.set_permissions)
def __repr__(self):
return self._cli_channel_id
class ClubSuite:
def get_all_clubs(guild): # returns list of club categories
roleNames= []
for role in guild.roles:
roleNames.append(role.name)
return filter(lambda x: x.name + ' Convener' in roleNames, guild.channels)
'''
Resolve club category from club category name
'''
def get_club(clubs, name):
for club in clubs:
if club.name.lower() == name.lower():
return club
return None
def get_club_roles(club):
roles = []
for role in club.guild.roles:
if role.name.startswith(club.name):
roles.append(role)
return roles
'''
Resolve club role from club and full role name
'''
def get_role(club, roleName):
for role in club.guild.roles:
print(role.name, roleName)
if role.name == roleName:
return role
return None
'''
Returns club category that matches proposed cli if there is one.
'''
def is_cli(clubs, channel):
for club in clubs:
if club.name.lower() + "-convenor-command-line" == channel.name:
return club
return False
'''
Returns the cli for the given club category channel
'''
def get_cli(category):
for channel in category.channels:
if category.name.lower() + '-convenor-command-line' == channel.name.lower():
return channel
return False
'''
Create a new role for the club.
Club - a guild category
role_name: a string of the new role name. Ex: Organizer
permissions: Permissions item to give the role
'''
async def add_role(club, role_name, permissions):
await club.guild.create_role(club.name + ' ' + role_name, permissions) # Unstable.
async def add_role_to_user(club, member, role):
await member.add_roles(ClubSuite.get_role(club, role))
# Add new convener to the club
async def add_convener(club, member, convener_role_name=None):
if convener_role_name == None:
convener_role_name = club.name + ' Convener'
await member.add_roles(ClubSuite.get_role(club, convener_role_name))
# Add new members to the club
async def add_member(club, member, member_role_name=None):
if member_role_name == None:
member_role_name = club.name + ' Member'
await member.add_roles(ClubSuite.get_role(club, member_role_name))
async def kick_member(club, member, member_role_name=None):
if member_role_name == None:
member_role_name = club.name + ' Member'
await member.remove_roles(ClubSuite.get_role(club, member_role_name))
async def ban_member(self, member):
# permaban member from the club
# do not allow join if on a list, i guess
pass
def unban_member(self, member):
# unban member from the club
# remove from the list, i guess
pass
'''
add text channel to resolved club category channel
'''
async def add_text_channel(club, channelName):
# add a text channel to this category.
await club.create_text_channel(channelName)
async def remove_text_channel(club, channel_name):
channel_name = channel_name.lower()
#remove text channel from category
for channel in club.text_channels:
if channel.name.lower() == channel_name:
await channel.delete()
return True
return False
async def get_text_channel(club, channel_name):
channel_name = channel_name.lower()
#remove text channel from category
for channel in club.text_channels:
if channel.name.lower() == channel_name:
return channel
return False
'''
add text channel to resolved club category channel
'''
async def add_voice_channel(club, channelName):
#add voice channel to category
await club.create_voice_channel(channelName)
async def remove_voice_channel(club, channel_name):
#remove voice channel from this category
channel_name = channel_name.lower()
for channel in club.voice_channels:
if channel.name == channel_name:
await channel.delete()
return True
return False
async def delete_category(club): # Provide your category
# Ask "are you sure" in the discord cli. if yes, delete the category.
# if no, don't. Return true or false if category was successfully/unsuccessfully deleted, respectively.
# Remove the clubnameX roles from the discord.
'''
TAKE LOG OF ALL PRIOR ACTIVITY FROM ALL EXISTING TEXT CHANNELS
'''
#TODO
'''
DELETE ASSOCIATED CHANNELS & CATEGORIES
'''
for channel in club.text_channels + club.voice_channels:
await channel.delete()
'''
DELETE ASSOCIATED CLUB ROLES
'''
for role in ClubSuite.get_club_roles(club):
await role.delete()
await club.delete()
def get_club_commands():
return ['!describe description - Registers your club description. You can put spaces in description.',
'!pin channel-to-pin-to-in-club message-to-pin - Pins message-to-pin to channel-to-pin-to-in-club',
'!unpin channel-to-unpin-from-in-club copypaste-message-to-unpin - unpins the message copy pasted from pinned messages from channel-to-unpin-from-in-club',
'!requestbot What you want your bot to do - Ask the Manager Bot Developers to make your club a bot! (They will get back to you with questions)',
'!kick member - Removes a member',
'!addvoicechannel name - Adds a voice channel',
'!addtextchannel name - Adds a text channel',
'!addconvener member - Makes member a convener',
'!ban member - Unimplemented', '!unban member - Unimplemented',
'!closeclub - Closes your club',
'!removevoicechannel name - Remove voice channel',
'!removetextchannel name - Remove text channel',
'!convenerhelp - Displays this message']
def get_club_command_examples():
return # not implemented
def get_help_message(channel):
commands = ClubSuite.get_club_commands()
send_text = 'Convener Commands in ' + channel.name + ' are:\n\t'
for command in commands:
send_text += command + '\n\t'
return send_text
async def processes_inc_command(message):
content = message.content.lower()
try:
maybe_club = ClubSuite.is_cli(ClubSuite.get_all_clubs(message.channel.guild), message.channel) #''' This will break the program later. message.channel can be a DM channel. find a way to make it so that that wont break the channel'''
if maybe_club == False:
print(content)
if content.startswith('!describeclub'):
cli = ClubSuite.get_cli(ClubSuite.get_club(ClubSuite.get_all_clubs(message.channel.guild), 'C-' + content[len('!describeclub '):]))
if cli != False:
for pin in await cli.pins():
if pin.content.startswith('DESCRIPTION SET TO: '):
await message.channel.send(content[len('!describeclub '):] + '\'s description is: ' + pin.content[len('DESCRIPTION SET TO: '):])
return True
await message.channel.send('Aww... ' + content[len('!describeclub '):] + ' hasn\'t set a description yet. Check back later!')
return True
return False
except:
print('could not find guild')
return False
if content.startswith('!addtextchannel '): # Add club text channel
await ClubSuite.add_text_channel(maybe_club, content[len('!addtextchannel '):]); return True
elif content.startswith('!removetextchannel'): # remove club text channel
await ClubSuite.remove_text_channel(maybe_club, content[len('!removetextchannel '):]); return True
elif content.startswith('!addvoicechannel'): #add club voice channel
await ClubSuite.add_voice_channel(maybe_club, content[len('!addvoicechannel '):]); return True
elif content.startswith('!removevoicechannel'): # remove club voice channel
await ClubSuite.remove_voice_channel(maybe_club, content[len('!removevoicechannel '):]); return True
elif content.startswith('!closeclub'):
await ClubSuite.delete_category(maybe_club); return True
elif content.startswith('!addmember'):
member = get_member_by_discord_name(message.guild, content[len('!addmember '):])
await ClubSuite.add_member(maybe_club, member); return True
elif content.startswith('!addconvener'):
member = get_member_by_discord_name(message.guild, content[len('!addconvener '):])#'''ADDCONVENER NEEDS SOME WORK'''
await ClubSuite.add_convener(maybe_club, member); return True
elif content.startswith('!kick'):
member = get_member_by_discord_name(message.guild, content[len('!kick '):])
await ClubSuite.kick_member(maybe_club, member); return True
elif content.startswith('!convenerhelp'):
await message.channel.send(ClubSuite.get_help_message(message.channel)); return True
elif content.startswith('!describe'):
await (await message.channel.send('DESCRIPTION SET TO: ' + content[len('!describe '):])).pin()
return True
elif content.startswith('!pin'):
terms = content.split(' ')
if len(terms) < 3:
await message.channel.send('!pin requires 3 things! Here\'s an example: !pin MyClubTextChannel what I want to pin and you can include spaces here', delete_after = 10)
channel = await ClubSuite.get_text_channel(maybe_club, terms[1])
if channel != False:
await (await channel.send(' '.join(terms[2:]))).pin()
elif content.startswith('!unpin'):
terms = content.split(' ')
if len(terms) < 3:
await message.channel.send('!pin requires 3 things! Here\'s an example: !pin MyClubTextChannel what I want to pin and you can include spaces here', delete_after = 10)
channel = await ClubSuite.get_text_channel(maybe_club, terms[1])
content = ' '.join(terms[2:])
if channel != False:
for pin in await channel.pins():
if pin.content == content:
await pin.unpin()
return True
await message.channel.send('!unpin requires 3 things! Here\'s an example: !pin TheClubChannelYourPinisin And what text copy pasted is in that pinned message', delete_after = 10)
elif content.startswith('!requestbot'):