update README & add functionality

pull/1/head
michael 2019-06-27 22:53:26 -07:00
parent f471094c58
commit e3f6f307b1
3 changed files with 94 additions and 25 deletions

View File

@ -1,2 +1,23 @@
# karl-marx-2 Karl Marx 2
A poll-based moderation bot to take care of that noisy scallywag in #general ===========
Karl Marx 2 takes a somewhat different spin on moderation for smaller servers (~10-35 users), handing the controls back to the users themselves. Instead of a single moderator issuing a command to mute, kick or banish a given user, the choice is left up to anyone and everyone present in the channel. Is the user at hand being annoying or spammy enough to be muted? Are they toxic enough to be kicked/banned? We'll take a vote!
<center><img src="mute_demo.png" width=350/></center>
I didn't have as much time as I would have liked to work on this, but I after Hack Week I intend to progressively flesh out its functionality beyond just moderation and further improve it.
Made with love. [Enjoy!](https://discordapp.com/oauth2/authorize?client_id=592852914553487370&permissions=8&scope=bot) :)
**IMPORTANT:** json storage is still under development.
Installation
------------
1. Clone the repo wherever you want and make sure you have python3 installed with the discord.py package. (If you don't then just `pip3 install discord.py` and you should be good to go!)
2. `python3 bot.py`
Commands
--------
- `>>mute` - Hold a 30-second vote to mute a user for 10 minutes. You can set different values in `config.json`.
- `>>exile` - Euphamism for banning a user, I guess. By default, the vote lasts 3 hours, and requires that there be at least 10 votes and a 50% majority. Like the `>>mute` command, you can also tweak settings in `config.json`.
- `>>anthem` - First verse of the Soviet National Anthem. Might need that at some point to show your communist pride.
- `>>ping` - Fun leftovers from when I was first setting up the bot. :P

94
bot.py
View File

@ -1,7 +1,18 @@
"""
Karl Marx 2
A bot by turtlebasket
"""
import asyncio
import json
import discord import discord
from discord.ext import commands from discord.ext import commands
from time import sleep
MUTE_VOTE_TIME = 10
MUTE_VOTER_MIN = 2
MUTE_TIME = 600 # 10 mins
BAN_VOTE_TIME = 8
BAN_VOTER_MIN = 4
bot = commands.Bot(command_prefix='>>') bot = commands.Bot(command_prefix='>>')
@bot.event @bot.event
@ -22,38 +33,36 @@ async def anthem(ctx):
command: anthem command: anthem
some people just need a reference, ya know? some people just need a reference, ya know?
""" """
await ctx.send("Soyuz nyerushimyiy ryespublik svobodnyikh\n"
"Splotila navyeki Vyelikaya Rus.\n"
"Da zdravstvuyet sozdannyiy volyey narodov\n"
"Yedinyiy, moguchiy Sovyetskiy Soyuz!\n")
await ctx.send( # not a command, just some functionality that's used across commands
"Soyuz nyerushimyiy ryespublik svobodnyikh\n" async def take_vote(ctx, question:str, wait_time):
"Splotila navyeki Vyelikaya Rus.\n"
"Da zdravstvuyet sozdannyiy volyey narodov\n"
"Yedinyiy, moguchiy Sovyetskiy Soyuz!\n"
)
@bot.command()
async def mute(ctx, target_user:str):
""" """
command: soft_mute take_vote(ctx, question:str) - Collects votes
The actual good stuff. ctx: pass from command function
If someone's spamming or being annoying, just mute 'em. Requires 3 votes by default. question: what to ask
returns [<all who want>, <all who don't want>].
It's up to the context/use case to decide how these should be used.
""" """
votey_message = await ctx.send( votey_message = await ctx.send("**=== NEW VOTE ===**\n{}".format(question))
"=== NEW MUTE VOTE ===\n"
"Mute {}?".format(str(target_user)))
await votey_message.add_reaction('') await votey_message.add_reaction('')
await votey_message.add_reaction('') await votey_message.add_reaction('')
sleep(10) await asyncio.sleep(wait_time)
finished_votey = await votey_message.channel.fetch_message(votey_message.id) finished_votey = await votey_message.channel.fetch_message(votey_message.id)
print(finished_votey.reactions)
all_in_favor = 0 all_in_favor = 0
not_in_favor = 0 not_in_favor = 0
for reaction in finished_votey.reactions: for reaction in finished_votey.reactions:
if str(reaction.emoji) == '': if str(reaction.emoji) == '':
all_in_favor += reaction.count-1 all_in_favor += reaction.count-1 # don't include bot's reaction
elif str(reaction.emoji) == '': elif str(reaction.emoji) == '':
not_in_favor += reaction.count-1 not_in_favor += reaction.count-1
else: else:
@ -63,11 +72,50 @@ async def mute(ctx, target_user:str):
"**=== VOTE RESULTS ===**\n" "**=== VOTE RESULTS ===**\n"
"✅ - {0}\n" "✅ - {0}\n"
"❌ - {1}\n".format(all_in_favor, not_in_favor)) "❌ - {1}\n".format(all_in_favor, not_in_favor))
return [all_in_favor, not_in_favor]
@bot.command()
async def mute(ctx, target_user:discord.User):
results = await take_vote(ctx, "Mute `{}`?".format(target_user), MUTE_VOTE_TIME)
all_in_favor = results[0]
not_in_favor = results[1]
if all_in_favor > 0 and all_in_favor - not_in_favor > 0:
# Take action to mute user
# add temp. role for mute
muted_role = await ctx.guild.create_role(name="Muted")
# edit role position to take precedence over other roles
await muted_role.edit(position=ctx.guild.get_member(target_user.id).top_role.position+1)
for channel in ctx.guild.channels:
await channel.set_permissions(muted_role, read_messages=True, send_messages=False, add_reactions=False, connect=False)
await ctx.guild.get_member(target_user.id).add_roles(muted_role)
await ctx.send("**{0}, the majority has ruled that you should be muted.** See ya in {1} minutes!".format(target_user, int(MUTE_TIME/60)))
await asyncio.sleep(MUTE_TIME)
await muted_role.delete()
if all_in_favor > 2 and all_in_favor - not_in_favor > 0:
await ctx.send("{} **has** been muted.".format(target_user))
else: else:
await ctx.send("{} **has not** been muted.".format(target_user)) await ctx.send("**{} has not been muted.**".format(target_user))
print("all in favor: {}".format(all_in_favor))
@bot.command()
async def roletest(ctx):
await ctx.send("`{}`".format(ctx.guild.roles))
@bot.command()
async def exile(ctx, target_user:discord.User):
results = await take_vote(ctx, "Ban `{}`?".format(target_user), BAN_VOTE_TIME)
all_in_favor = results[0]
not_in_favor = results[1]
if all_in_favor > not_in_favor and all_in_favor >= BAN_VOTER_MIN: # change to 10 later
await ctx.guild.ban(target_user)
await ctx.send(":crab: :crab: `{}` IS GONE :crab: :crab:".format(target_user.name))
elif all_in_favor <= all_in_favor:
await ctx.send("The majority (>50%) did not decide on banning `{}`.".format(target_user.name))
elif all_in_favor < 1:
await ctx.send("Not enough users voted to ban `{}`.".format(target_user.name))
bot.run(open("token.txt").read().strip()) bot.run(open("token.txt").read().strip())

BIN
mute_demo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB