add functionality for people to block other users they don't want to interact with
This commit is contained in:
		
							parent
							
								
									0c84b3cebd
								
							
						
					
					
						commit
						60a1f8b827
					
				
					 2 changed files with 122 additions and 19 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
config.json
 | 
			
		||||
blocks.json
 | 
			
		||||
 | 
			
		||||
# ---> Python
 | 
			
		||||
# Byte-compiled / optimized / DLL files
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										140
									
								
								waggle-dance.py
									
										
									
									
									
								
							
							
						
						
									
										140
									
								
								waggle-dance.py
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -4,20 +4,90 @@ import asyncio
 | 
			
		|||
import discord
 | 
			
		||||
import json
 | 
			
		||||
import random
 | 
			
		||||
import re
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
BLOCKS_FILE = 'blocks.json'
 | 
			
		||||
 | 
			
		||||
def get_blocks():
 | 
			
		||||
    try:
 | 
			
		||||
        with open(BLOCKS_FILE) as f:
 | 
			
		||||
            return {int(k): v for (k, v) in json.load(f).items()}
 | 
			
		||||
    except FileNotFoundError:
 | 
			
		||||
        return {}
 | 
			
		||||
 | 
			
		||||
def add_block(requester, target):
 | 
			
		||||
    blocks = get_blocks()
 | 
			
		||||
    if requester not in blocks:
 | 
			
		||||
        blocks[requester] = []
 | 
			
		||||
    if target not in blocks[requester]:
 | 
			
		||||
        blocks[requester].append(target)
 | 
			
		||||
    with open(BLOCKS_FILE, 'w') as f:
 | 
			
		||||
        json.dump(blocks, f)
 | 
			
		||||
 | 
			
		||||
def remove_block(requester, target):
 | 
			
		||||
    blocks = get_blocks()
 | 
			
		||||
    if requester not in blocks:
 | 
			
		||||
        return
 | 
			
		||||
    while target in blocks[requester]:
 | 
			
		||||
        blocks[requester].remove(target)
 | 
			
		||||
    if len(blocks[requester]) == 0:
 | 
			
		||||
        del blocks[requester]
 | 
			
		||||
    with open(BLOCKS_FILE, 'w') as f:
 | 
			
		||||
        json.dump(blocks, f)
 | 
			
		||||
 | 
			
		||||
def matchings(l):
 | 
			
		||||
    if len(l) == 0:
 | 
			
		||||
    count = len(l)
 | 
			
		||||
    if count == 0:
 | 
			
		||||
        return []
 | 
			
		||||
    l = l.copy()
 | 
			
		||||
    random.shuffle(l)
 | 
			
		||||
    center = l.pop()
 | 
			
		||||
    ids = set(u.id for u in l)
 | 
			
		||||
 | 
			
		||||
    blocks = get_blocks()
 | 
			
		||||
    block_pairs = set()
 | 
			
		||||
    for r in blocks:
 | 
			
		||||
        if r in ids:
 | 
			
		||||
            for t in blocks[r]:
 | 
			
		||||
                if t in ids:
 | 
			
		||||
                    block_pairs.add((min(r,t), max(r,t)))
 | 
			
		||||
    disjoint_pairs = []
 | 
			
		||||
    while True:
 | 
			
		||||
        paired = set(u for pair in disjoint_pairs for u in pair)
 | 
			
		||||
        remaining = set(p for p in block_pairs if p[0] not in paired and p[1] not in paired)
 | 
			
		||||
        if len(remaining) == 0:
 | 
			
		||||
            break
 | 
			
		||||
        disjoint_pairs.append(remaining.pop())
 | 
			
		||||
 | 
			
		||||
    circle = [None]*(count - 1)
 | 
			
		||||
    center = None
 | 
			
		||||
    for i in range(count // 2):
 | 
			
		||||
        if len(disjoint_pairs) != 0:
 | 
			
		||||
            p = disjoint_pairs.pop()
 | 
			
		||||
            l = [u for u in l if u.id not in p]
 | 
			
		||||
            u0 = p[0]
 | 
			
		||||
            u1 = p[1]
 | 
			
		||||
        else:
 | 
			
		||||
            u0 = l.pop()
 | 
			
		||||
            u1 = l.pop()
 | 
			
		||||
 | 
			
		||||
        circle[i] = u0
 | 
			
		||||
        if i != count // 2 - 1:
 | 
			
		||||
            circle[-(i+1)] = u1
 | 
			
		||||
        else:
 | 
			
		||||
            center = u1
 | 
			
		||||
 | 
			
		||||
    result = []
 | 
			
		||||
    for i in range(len(l)):
 | 
			
		||||
        matching = [(center, l[i])]
 | 
			
		||||
        for j in range(1, (len(l)-1)//2 + 1):
 | 
			
		||||
            matching.append((l[(i-j)%len(l)], l[(i+j)%len(l)]))
 | 
			
		||||
    for i in range(len(circle)):
 | 
			
		||||
        matching = [(center, circle[i])]
 | 
			
		||||
        for j in range(1, (len(circle)-1)//2 + 1):
 | 
			
		||||
            matching.append((circle[(i-j)%len(circle)], circle[(i+j)%len(circle)]))
 | 
			
		||||
        result.append(matching)
 | 
			
		||||
 | 
			
		||||
    random.shuffle(result)
 | 
			
		||||
    for i in range(len(result)):
 | 
			
		||||
        random.shuffle(result[i])
 | 
			
		||||
    result = [matching for matching in result if all((min(match[0].id,match[1].id), max(match[0].id,match[1].id)) not in block_pairs for match in matching)]
 | 
			
		||||
    return result
 | 
			
		||||
 | 
			
		||||
async def delete_if_possible(channels):
 | 
			
		||||
| 
						 | 
				
			
			@ -39,15 +109,7 @@ with open('config.json') as f:
 | 
			
		|||
 | 
			
		||||
client = discord.Client()
 | 
			
		||||
 | 
			
		||||
@client.event
 | 
			
		||||
async def on_ready():
 | 
			
		||||
    print('logged in as {0.user}'.format(client), file=sys.stderr)
 | 
			
		||||
 | 
			
		||||
@client.event
 | 
			
		||||
async def on_message(message):
 | 
			
		||||
    if message.author == client.user:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
async def handle_guild_message(message):
 | 
			
		||||
    if not message.content.startswith('!waggle'):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -81,10 +143,6 @@ async def on_message(message):
 | 
			
		|||
        participants.remove(message.author)
 | 
			
		||||
        await message.channel.send('leaving out {} so we have an even number of participants'.format(message.author.mention))
 | 
			
		||||
 | 
			
		||||
    if len(participants) == 0:
 | 
			
		||||
        await message.channel.send('there are no participants! :(')
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    mention_all = ' '.join(u.mention for u in participants)
 | 
			
		||||
 | 
			
		||||
    schedule = matchings(participants)
 | 
			
		||||
| 
						 | 
				
			
			@ -92,6 +150,10 @@ async def on_message(message):
 | 
			
		|||
    if rounds:
 | 
			
		||||
        schedule = schedule[:rounds]
 | 
			
		||||
 | 
			
		||||
    if len(schedule) == 0:
 | 
			
		||||
        await message.channel.send("there aren't enough people for pollination right now :(")
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    pollination_channels = []
 | 
			
		||||
    channel_names = config['channel_names'].copy()
 | 
			
		||||
    exception_count = 0
 | 
			
		||||
| 
						 | 
				
			
			@ -147,4 +209,44 @@ async def on_message(message):
 | 
			
		|||
 | 
			
		||||
    await delete_if_possible(pollination_channels)
 | 
			
		||||
 | 
			
		||||
async def handle_dm(message):
 | 
			
		||||
    requester = message.author.id
 | 
			
		||||
    match = re.search('@([^#]+)#([0-9a-f]+)', message.content)
 | 
			
		||||
    if match:
 | 
			
		||||
        handle = match.group(0)
 | 
			
		||||
        name = match.group(1)
 | 
			
		||||
        discriminator = match.group(2)
 | 
			
		||||
        matching_users = [u for u in client.users if u.name == name and u.discriminator == discriminator]
 | 
			
		||||
        if len(matching_users) == 0:
 | 
			
		||||
            await message.channel.send("sorry, I can't find user {}".format(handle))
 | 
			
		||||
        else:
 | 
			
		||||
            target = matching_users[0].id
 | 
			
		||||
            if target in get_blocks().get(requester, []):
 | 
			
		||||
                await message.channel.send("removing {} from your list of blocked users for pollination".format(handle))
 | 
			
		||||
                remove_block(requester, target)
 | 
			
		||||
            else:
 | 
			
		||||
                await message.channel.send("adding {} to your list of blocked users for pollination".format(handle))
 | 
			
		||||
                add_block(requester, target)
 | 
			
		||||
 | 
			
		||||
    blocks = get_blocks().get(requester, [])
 | 
			
		||||
    if len(blocks) == 0:
 | 
			
		||||
        await message.channel.send("you currently don't have anyone blocked for pollination")
 | 
			
		||||
    else:
 | 
			
		||||
        await message.channel.send("your current list of blocked users for pollination is:\n{}".format('\n'.join('@{}#{}'.format(u.name, u.discriminator) for u in [client.get_user(uid) for uid in blocks] if u is not None)))
 | 
			
		||||
    await message.channel.send("to block or unblock a user, DM me their handle, like @creep#0000. to see this message and your list of blocked users, DM me something random. buzz buzz!")
 | 
			
		||||
 | 
			
		||||
@client.event
 | 
			
		||||
async def on_ready():
 | 
			
		||||
    print('logged in as {0.user}'.format(client), file=sys.stderr)
 | 
			
		||||
 | 
			
		||||
@client.event
 | 
			
		||||
async def on_message(message):
 | 
			
		||||
    if message.author == client.user:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    if isinstance(message.channel, discord.TextChannel):
 | 
			
		||||
        await handle_guild_message(message)
 | 
			
		||||
    elif isinstance(message.channel, discord.DMChannel):
 | 
			
		||||
        await handle_dm(message)
 | 
			
		||||
 | 
			
		||||
client.run(config['token'])
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue