Skip to content
Snippets Groups Projects
BottyBuildMain.py 17.1 KiB
Newer Older
# -*- coding: utf-8 -*-
"""
Created on Sat Sep  5 14:09:29 2020

@author: josep
"""

import discord
from discord.ext import commands, tasks
import smtplib, ssl
from datetime import datetime, timedelta
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
IS1_4M's avatar
IS1_4M committed
from rssfeedtest import get_today_at_earlham
import json

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'
IS1_4M's avatar
IS1_4M committed
with open('../../../ECHackersBotCreds/credentials.json') as file:
    credentials = json.load(file)

student_role_name = 'ECStudent'
faculty_role_name = 'ECFaculty'
general_user_role_names = [student_role_name, faculty_role_name]
account_password = credentials['email_password']
clubs = []
users = []

#client = discord.Client()
client = commands.Bot('!')  

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


# I need a var section big time so i can call for updates
# THIS NEEDS PRIORITY UPDATES
@tasks.loop(hours=24)
async def update_today_at_schools():
    try:
        print('invoked update functionm')
        # ASSUME THE GUILD IS EARLHAM COLLEGe
        print(client.guilds)
        for guild in client.guilds:
            print('searching guild:', guild.name)
            today_at_school = None
            today_at_virtual_school = None
IS1_4M's avatar
IS1_4M committed
            virtual_annoucements, local_annoucements = get_today_at_earlham()
            for channel in guild.channels:
                print(channel.name)
                print('\t', channel.name == 'today-at-earlham', channel.name == 'today-at-remote-earlham')
                if channel.name == 'today-at-earlham':
                    await channel.send('Today at Earlham ' + str(datetime.today()) + ': \n\n')
                    for annoucement in local_annoucements:
                        await channel.send(annoucement)
                elif channel.name == 'today-at-remote-earlham':
                    await channel.send('Today at Remote Earlham ' + str(datetime.today()) + ': \n\n')
                    for annoucement in virtual_annoucements:
                        await channel.send(annoucement)
    except:
        return
@update_today_at_schools.before_loop
async def before_update_today_at_schools():
    print('started update before loop')
    hour = 8
    minute = 5
    await client.wait_until_ready()
    print('check1')
    now = datetime.now()
    future = datetime(now.year, now.month, now.day, hour, minute, 0)
    #future = datetime.now() + timedelta(seconds=5)
    print('check2')
    print(now.hour, hour, now.minute, minute, now.hour >= hour, now.minute > minute)
    if now.hour >= hour and now.minute > minute:
        print('adding a day')
        future += timedelta(days=1)
        print('added a day')
    print((future - now).seconds)
    print('sleeping for (s): ', (future-now).seconds)
    await sleep((future-now).seconds)
    
@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... Moved you to the full discord. Look at all channels for information!', delete_after = 5)
                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
                if '@' in content:
                    content = content[:content.index('@')]
                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('!'):] + '@earlham.edu', 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(general_user_role_names)
                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.process_commands(message):
            await message.channel.send('Succeeded...', delete_after=3)
            return
        
        '''
            GENERAL COMMANDS GO HERE
        '''
        if content.startswith('!makeclub'):
            clubName = content[len('!makeclub '):].upper()
IS1_4M's avatar
IS1_4M committed
            clubName = clubName.replace(' ', '-')
            print(clubName)
            clubs = list(ClubSuite.get_all_clubs(message.channel.guild))
            # make sure we're not making a duplicate club
            for i in range(len(clubs)):
IS1_4M's avatar
IS1_4M committed
                clubs[i] = clubs[i].name.upper()
            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'):
IS1_4M's avatar
IS1_4M committed
            target = ('c-' + content[len('!joinclub '):]).upper().replace(' ','-')
            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'):
IS1_4M's avatar
IS1_4M committed
            target = ('c-' + content[len('!leaveclub '):]).upper().replace(' ','-')
            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') or content.startswith('!ocommands') or content.startswith('!ccommands') or content.startswith('!rcommands'):
Joseph's avatar
Joseph committed
            commands = ['!clublist\n\t\t - Lists all clubs in ' + message.channel.guild.name, '!describeclub Clubname\n\t\t - Gives a Clubname\'s self-provided description', '!joinclub Clubname\n\t\t - Joins the club Clubname', '!leaveclub\n\t\t - Leaves a server\'s club',
IS1_4M's avatar
IS1_4M committed
                        '!makeclub Clubname\n\t\t - Makes the club 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 = '[WIP] 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()
IS1_4M's avatar
IS1_4M committed
        elif content.startswith('!whatcanido'):
            options = '''\n    -Have constructive conversations about topics you\'re passionate about
                - Play games with people you know and love from Earlham
                - Host Spaces for your friends to hang out with other people
                - Learn more about whats happening on Earlham\'s campus digitally
                - Do 24/7 options for meeting and greeting other Earlham Students
                - Connect with the Earlham Community 
                - And much much more!'''
            await message.channel.send('What can you do? You can:' + options)
        elif content.startswith('!whatwaycanidoit'):
            options = '''\n    - Click a text channel in the side bar to have a conversation
                - Click voice channel in the side bar to have a face to face conversation and/or share screens!
                - do !ocommands for ways to hang out with your Earlham friends
                - do !ccommands for ways to join, make, and interact with clubs in other ways
                - do !rcommands for ways to share your voice on impactful topics and do difference making!
                - do !help for general other commands, and !examples for how to use them
            '''
            await message.channel.send('What ways can do you things? You can:' + options)
        # 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)
        
IS1_4M's avatar
IS1_4M committed
    else:
        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')
        if maybe_auth:
            await message.delete(delay=3)
    # 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
update_today_at_schools.start()
client.run(credentials['bot_token'])