BottyBuildMain.py 17.1 KB
Newer Older
Joseph's avatar
Joseph committed
1
2
3
4
5
6
7
8
# -*- coding: utf-8 -*-
"""
Created on Sat Sep  5 14:09:29 2020

@author: josep
"""

import discord
9
from discord.ext import commands, tasks
Joseph's avatar
Joseph committed
10
import smtplib, ssl
11
from datetime import datetime, timedelta
Joseph's avatar
Joseph committed
12
13
14
15
16
17
18
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
19
from test_get_mail import get_today_at_school
20
import json
Joseph's avatar
Joseph committed
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

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
40
with open('../../../ECHackersBotCreds/credentials.json') as file:
41
    credentials = json.load(file)
Joseph's avatar
Joseph committed
42
43
44

student_role_name = 'ECStudent'
faculty_role_name = 'ECFaculty'
45
general_user_role_names = [student_role_name, faculty_role_name]
46
account_password = credentials['email_password']
Joseph's avatar
Joseph committed
47
48
49
clubs = []
users = []

50
51
#client = discord.Client()
client = commands.Bot('!')  
Joseph's avatar
Joseph committed
52
53
54
55
56
57
58

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

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

# 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
            virtual_annoucements, local_annoucements = get_today_at_school(send_account_email, account_password)
            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)
    
Joseph's avatar
Joseph committed
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
@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)
148
                    await message.channel.send('Authenticatoin succeeded... Moved you to the full discord. Look at all channels for information!', delete_after = 5)
Joseph's avatar
Joseph committed
149
150
151
                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
152
153
                if '@' in content:
                    content = content[:content.index('@')]
Joseph's avatar
Joseph committed
154
155
                print('sent email to ' + content[len('!'):])
                auth_user.send_auth_email_to_addr(content[len('!'):], domain_dest,send_account_email, account_password)
156
                await message.channel.send('Send auth code to: ' + content[len('!'):] + '@earlham.edu', delete_after = 3)
Joseph's avatar
Joseph committed
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
            #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)
184
                await newClub._init(general_user_role_names)
Joseph's avatar
Joseph committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
                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
207
        if await ClubSuite.process_commands(message):
Joseph's avatar
Joseph committed
208
209
210
211
212
213
214
215
            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
216
217
            clubName = clubName.replace(' ', '-')
            print(clubName)
Joseph's avatar
Joseph committed
218
219
220
            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
221
                clubs[i] = clubs[i].name.upper()
Joseph's avatar
Joseph committed
222
223
224
225
226
227
228
229
            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
230
            target = ('c-' + content[len('!joinclub '):]).upper().replace(' ','-')
Joseph's avatar
Joseph committed
231
232
233
234
235
236
237
238
            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
239
            target = ('c-' + content[len('!leaveclub '):]).upper().replace(' ','-')
Joseph's avatar
Joseph committed
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
            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 
270
        elif content.startswith('!help') or content.startswith('!ocommands') or content.startswith('!ccommands') or content.startswith('!rcommands'):
Joseph's avatar
Joseph committed
271
            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
272
                        '!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.',
Joseph's avatar
Joseph committed
273
274
275
276
                        '!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',]
277
            send_text = '[WIP] Commands in ' + message.channel.guild.name + ' are:\n\t'
Joseph's avatar
Joseph committed
278
279
280
281
            for command in commands:
                send_text += command + '\n\t'
            await message.channel.send(send_text)
            return 
282
        
Joseph's avatar
Joseph committed
283
284
285
286
287
288
        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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
        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)
Joseph's avatar
Joseph committed
307
308
309
310
311
312
313
314
315
        # 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
316
317
318
319
320
321
322
    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)
Joseph's avatar
Joseph committed
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
    # 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
339
340
update_today_at_schools.start()
client.run(credentials['bot_token'])