mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
347 lines
14 KiB
Python
347 lines
14 KiB
Python
import discord
|
||
from discord.ext import commands
|
||
from .utils.chat_formatting import *
|
||
from random import randint
|
||
from random import choice as randchoice
|
||
import datetime
|
||
import time
|
||
import aiohttp
|
||
import asyncio
|
||
|
||
settings = {"POLL_DURATION" : 60}
|
||
|
||
class General:
|
||
"""General commands."""
|
||
|
||
def __init__(self, bot):
|
||
self.bot = bot
|
||
self.stopwatches = {}
|
||
self.ball = ["As I see it, yes", "It is certain", "It is decidedly so", "Most likely", "Outlook good",
|
||
"Signs point to yes", "Without a doubt", "Yes", "Yes – definitely", "You may rely on it", "Reply hazy, try again",
|
||
"Ask again later", "Better not tell you now", "Cannot predict now", "Concentrate and ask again",
|
||
"Don't count on it", "My reply is no", "My sources say no", "Outlook not so good", "Very doubtful"]
|
||
self.poll_sessions = []
|
||
|
||
@commands.command(hidden=True)
|
||
async def ping(self):
|
||
"""Pong."""
|
||
await self.bot.say("Pong.")
|
||
|
||
@commands.command()
|
||
async def choose(self, *choices):
|
||
"""Chooses between multiple choices.
|
||
|
||
To denote multiple choices, you should use double quotes.
|
||
"""
|
||
choices = [escape_mass_mentions(choice) for choice in choices]
|
||
if len(choices) < 2:
|
||
await self.bot.say('Not enough choices to pick from.')
|
||
else:
|
||
await self.bot.say(randchoice(choices))
|
||
|
||
@commands.command(pass_context=True)
|
||
async def roll(self, ctx, number : int = 100):
|
||
"""Rolls random number (between 1 and user choice)
|
||
|
||
Defaults to 100.
|
||
"""
|
||
author = ctx.message.author
|
||
if number > 1:
|
||
n = randint(1, number)
|
||
await self.bot.say("{} :game_die: {} :game_die:".format(author.mention, n))
|
||
else:
|
||
await self.bot.say("{} Maybe higher than 1? ;P".format(author.mention))
|
||
|
||
@commands.command(pass_context=True)
|
||
async def flip(self, ctx, user : discord.Member=None):
|
||
"""Flips a coin... or a user.
|
||
|
||
Defaults to coin.
|
||
"""
|
||
if user != None:
|
||
msg = ""
|
||
if user.id == self.bot.user.id:
|
||
user = ctx.message.author
|
||
msg = "Nice try. You think this is funny? How about *this* instead:\n\n"
|
||
char = "abcdefghijklmnopqrstuvwxyz"
|
||
tran = "ɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz"
|
||
table = str.maketrans(char, tran)
|
||
name = user.name.translate(table)
|
||
char = char.upper()
|
||
tran = "∀qƆpƎℲפHIſʞ˥WNOԀQᴚS┴∩ΛMX⅄Z"
|
||
table = str.maketrans(char, tran)
|
||
name = name.translate(table)
|
||
await self.bot.say(msg + "(╯°□°)╯︵ " + name[::-1])
|
||
else:
|
||
await self.bot.say("*flips a coin and... " + randchoice(["HEADS!*", "TAILS!*"]))
|
||
|
||
@commands.command(pass_context=True)
|
||
async def rps(self, ctx, choice : str):
|
||
"""Play rock paper scissors"""
|
||
author = ctx.message.author
|
||
rpsbot = {"rock" : ":moyai:",
|
||
"paper": ":page_facing_up:",
|
||
"scissors":":scissors:"}
|
||
choice = choice.lower()
|
||
if choice in rpsbot.keys():
|
||
botchoice = randchoice(list(rpsbot.keys()))
|
||
msgs = {
|
||
"win": " You win {}!".format(author.mention),
|
||
"square": " We're square {}!".format(author.mention),
|
||
"lose": " You lose {}!".format(author.mention)
|
||
}
|
||
if choice == botchoice:
|
||
await self.bot.say(rpsbot[botchoice] + msgs["square"])
|
||
elif choice == "rock" and botchoice == "paper":
|
||
await self.bot.say(rpsbot[botchoice] + msgs["lose"])
|
||
elif choice == "rock" and botchoice == "scissors":
|
||
await self.bot.say(rpsbot[botchoice] + msgs["win"])
|
||
elif choice == "paper" and botchoice == "rock":
|
||
await self.bot.say(rpsbot[botchoice] + msgs["win"])
|
||
elif choice == "paper" and botchoice == "scissors":
|
||
await self.bot.say(rpsbot[botchoice] + msgs["lose"])
|
||
elif choice == "scissors" and botchoice == "rock":
|
||
await self.bot.say(rpsbot[botchoice] + msgs["lose"])
|
||
elif choice == "scissors" and botchoice == "paper":
|
||
await self.bot.say(rpsbot[botchoice] + msgs["win"])
|
||
else:
|
||
await self.bot.say("Choose rock, paper or scissors.")
|
||
|
||
@commands.command(name="8", aliases=["8ball"])
|
||
async def _8ball(self, *, question : str):
|
||
"""Ask 8 ball a question
|
||
|
||
Question must end with a question mark.
|
||
"""
|
||
if question.endswith("?") and question != "?":
|
||
await self.bot.say("`" + randchoice(self.ball) + "`")
|
||
else:
|
||
await self.bot.say("That doesn't look like a question.")
|
||
|
||
@commands.command(aliases=["sw"], pass_context=True)
|
||
async def stopwatch(self, ctx):
|
||
"""Starts/stops stopwatch"""
|
||
author = ctx.message.author
|
||
if not author.id in self.stopwatches:
|
||
self.stopwatches[author.id] = int(time.perf_counter())
|
||
await self.bot.say(author.mention + " Stopwatch started!")
|
||
else:
|
||
tmp = abs(self.stopwatches[author.id] - int(time.perf_counter()))
|
||
tmp = str(datetime.timedelta(seconds=tmp))
|
||
await self.bot.say(author.mention + " Stopwatch stopped! Time: **" + tmp + "**")
|
||
self.stopwatches.pop(author.id, None)
|
||
|
||
@commands.command()
|
||
async def lmgtfy(self, *, search_terms : str):
|
||
"""Creates a lmgtfy link"""
|
||
search_terms = escape_mass_mentions(search_terms.replace(" ", "+"))
|
||
await self.bot.say("http://lmgtfy.com/?q={}".format(search_terms))
|
||
|
||
@commands.command(no_pm=True, hidden=True)
|
||
async def hug(self, user : discord.Member, intensity : int=1):
|
||
"""Because everyone likes hugs
|
||
|
||
Up to 10 intensity levels."""
|
||
name = " *" + user.name + "*"
|
||
if intensity <= 0:
|
||
msg = "(っ˘̩╭╮˘̩)っ" + name
|
||
elif intensity <= 3:
|
||
msg = "(っ´▽`)っ" + name
|
||
elif intensity <= 6:
|
||
msg = "╰(*´︶`*)╯" + name
|
||
elif intensity <= 9:
|
||
msg = "(つ≧▽≦)つ" + name
|
||
elif intensity >= 10:
|
||
msg = "(づ ̄ ³ ̄)づ" + name + " ⊂(´・ω・`⊂)"
|
||
await self.bot.say(msg)
|
||
|
||
@commands.command(pass_context=True, no_pm=True)
|
||
async def userinfo(self, ctx, user : discord.Member = None):
|
||
"""Shows users's informations"""
|
||
author = ctx.message.author
|
||
if not user:
|
||
user = author
|
||
roles = [x.name for x in user.roles if x.name != "@everyone"]
|
||
if not roles: roles = ["None"]
|
||
data = "```python\n"
|
||
data += "Name: {}\n".format(escape_mass_mentions(str(user)))
|
||
data += "ID: {}\n".format(user.id)
|
||
passed = (ctx.message.timestamp - user.created_at).days
|
||
data += "Created: {} ({} days ago)\n".format(user.created_at, passed)
|
||
passed = (ctx.message.timestamp - user.joined_at).days
|
||
data += "Joined: {} ({} days ago)\n".format(user.joined_at, passed)
|
||
data += "Roles: {}\n".format(", ".join(roles))
|
||
data += "Avatar: {}\n".format(user.avatar_url)
|
||
data += "```"
|
||
await self.bot.say(data)
|
||
|
||
@commands.command(pass_context=True, no_pm=True)
|
||
async def serverinfo(self, ctx):
|
||
"""Shows server's informations"""
|
||
server = ctx.message.server
|
||
online = str(len([m.status for m in server.members if str(m.status) == "online" or str(m.status) == "idle"]))
|
||
total_users = str(len(server.members))
|
||
text_channels = len([x for x in server.channels if str(x.type) == "text"])
|
||
voice_channels = len(server.channels) - text_channels
|
||
|
||
data = "```python\n"
|
||
data += "Name: {}\n".format(server.name)
|
||
data += "ID: {}\n".format(server.id)
|
||
data += "Region: {}\n".format(server.region)
|
||
data += "Users: {}/{}\n".format(online, total_users)
|
||
data += "Text channels: {}\n".format(text_channels)
|
||
data += "Voice channels: {}\n".format(voice_channels)
|
||
data += "Roles: {}\n".format(len(server.roles))
|
||
passed = (ctx.message.timestamp - server.created_at).days
|
||
data += "Created: {} ({} days ago)\n".format(server.created_at, passed)
|
||
data += "Owner: {}\n".format(server.owner)
|
||
data += "Icon: {}\n".format(server.icon_url)
|
||
data += "```"
|
||
await self.bot.say(data)
|
||
|
||
@commands.command()
|
||
async def urban(self, *, search_terms : str, definition_number : int=1):
|
||
"""Urban Dictionary search
|
||
|
||
Definition number must be between 1 and 10"""
|
||
# definition_number is just there to show up in the help
|
||
# all this mess is to avoid forcing double quotes on the user
|
||
search_terms = search_terms.split(" ")
|
||
try:
|
||
if len(search_terms) > 1:
|
||
pos = int(search_terms[-1]) - 1
|
||
search_terms = search_terms[:-1]
|
||
else:
|
||
pos = 0
|
||
if pos not in range(0, 11): # API only provides the
|
||
pos = 0 # top 10 definitions
|
||
except ValueError:
|
||
pos = 0
|
||
search_terms = "+".join(search_terms)
|
||
url = "http://api.urbandictionary.com/v0/define?term=" + search_terms
|
||
try:
|
||
async with aiohttp.get(url) as r:
|
||
result = await r.json()
|
||
if result["list"]:
|
||
definition = result['list'][pos]['definition']
|
||
example = result['list'][pos]['example']
|
||
defs = len(result['list'])
|
||
msg = ("**Definition #{} out of {}:\n**{}\n\n"
|
||
"**Example:\n**{}".format(pos+1, defs, definition,
|
||
example))
|
||
msg = pagify(msg, ["\n"])
|
||
for page in msg:
|
||
await self.bot.say(page)
|
||
else:
|
||
await self.bot.say("Your search terms gave no results.")
|
||
except IndexError:
|
||
await self.bot.say("There is no definition #{}".format(pos+1))
|
||
except:
|
||
await self.bot.say("Error.")
|
||
|
||
@commands.command(pass_context=True, no_pm=True)
|
||
async def poll(self, ctx, *text):
|
||
"""Starts/stops a poll
|
||
|
||
Usage example:
|
||
poll Is this a poll?;Yes;No;Maybe
|
||
poll stop"""
|
||
message = ctx.message
|
||
if len(text) == 1:
|
||
if text[0].lower() == "stop":
|
||
await self.endpoll(message)
|
||
return
|
||
if not self.getPollByChannel(message):
|
||
check = " ".join(text).lower()
|
||
if "@everyone" in check or "@here" in check:
|
||
await self.bot.say("Nice try.")
|
||
return
|
||
p = NewPoll(message, self)
|
||
if p.valid:
|
||
self.poll_sessions.append(p)
|
||
await p.start()
|
||
else:
|
||
await self.bot.say("poll question;option1;option2 (...)")
|
||
else:
|
||
await self.bot.say("A poll is already ongoing in this channel.")
|
||
|
||
async def endpoll(self, message):
|
||
if self.getPollByChannel(message):
|
||
p = self.getPollByChannel(message)
|
||
if p.author == message.author.id: # or isMemberAdmin(message)
|
||
await self.getPollByChannel(message).endPoll()
|
||
else:
|
||
await self.bot.say("Only admins and the author can stop the poll.")
|
||
else:
|
||
await self.bot.say("There's no poll ongoing in this channel.")
|
||
|
||
def getPollByChannel(self, message):
|
||
for poll in self.poll_sessions:
|
||
if poll.channel == message.channel:
|
||
return poll
|
||
return False
|
||
|
||
async def check_poll_votes(self, message):
|
||
if message.author.id != self.bot.user.id:
|
||
if self.getPollByChannel(message):
|
||
self.getPollByChannel(message).checkAnswer(message)
|
||
|
||
|
||
class NewPoll():
|
||
def __init__(self, message, main):
|
||
self.channel = message.channel
|
||
self.author = message.author.id
|
||
self.client = main.bot
|
||
self.poll_sessions = main.poll_sessions
|
||
msg = message.content[6:]
|
||
msg = msg.split(";")
|
||
if len(msg) < 2: # Needs at least one question and 2 choices
|
||
self.valid = False
|
||
return None
|
||
else:
|
||
self.valid = True
|
||
self.already_voted = []
|
||
self.question = msg[0]
|
||
msg.remove(self.question)
|
||
self.answers = {}
|
||
i = 1
|
||
for answer in msg: # {id : {answer, votes}}
|
||
self.answers[i] = {"ANSWER" : answer, "VOTES" : 0}
|
||
i += 1
|
||
|
||
async def start(self):
|
||
msg = "**POLL STARTED!**\n\n{}\n\n".format(self.question)
|
||
for id, data in self.answers.items():
|
||
msg += "{}. *{}*\n".format(id, data["ANSWER"])
|
||
msg += "\nType the number to vote!"
|
||
await self.client.send_message(self.channel, msg)
|
||
await asyncio.sleep(settings["POLL_DURATION"])
|
||
if self.valid:
|
||
await self.endPoll()
|
||
|
||
async def endPoll(self):
|
||
self.valid = False
|
||
msg = "**POLL ENDED!**\n\n{}\n\n".format(self.question)
|
||
for data in self.answers.values():
|
||
msg += "*{}* - {} votes\n".format(data["ANSWER"], str(data["VOTES"]))
|
||
await self.client.send_message(self.channel, msg)
|
||
self.poll_sessions.remove(self)
|
||
|
||
def checkAnswer(self, message):
|
||
try:
|
||
i = int(message.content)
|
||
if i in self.answers.keys():
|
||
if message.author.id not in self.already_voted:
|
||
data = self.answers[i]
|
||
data["VOTES"] += 1
|
||
self.answers[i] = data
|
||
self.already_voted.append(message.author.id)
|
||
except ValueError:
|
||
pass
|
||
|
||
|
||
def setup(bot):
|
||
n = General(bot)
|
||
bot.add_listener(n.check_poll_votes, "on_message")
|
||
bot.add_cog(n)
|