hug back and hugs stats

This commit is contained in:
ddorn 2020-05-17 15:06:37 +02:00
parent 42faffb7dd
commit 7f32524ead
3 changed files with 185 additions and 33 deletions

View File

@ -3,7 +3,9 @@ import datetime
import io
import itertools
import random
import re
import urllib
from collections import defaultdict, Counter
from dataclasses import dataclass, field
from operator import attrgetter
from time import time
@ -47,12 +49,37 @@ class Joke(yaml.YAMLObject):
file: str = None
HUG_RE = re.compile(r"^(?P<hugger>\d+) -> (?P<hugged>\d+) \| (?P<text>.*)$")
class Hug:
def __init__(self, hugger, hugged, text):
self.hugger = hugger
self.hugged = hugged
self.text = text
@classmethod
def from_str(cls, line: str):
match = HUG_RE.match(line)
if not match:
raise ValueError(f"'{line}' is not a valid hug format.")
hugger = int(match.group("hugger"))
hugged = int(match.group("hugged"))
text = match.group("text")
return cls(hugger, hugged, text)
def __repr__(self):
return f"{self.hugger} -> {self.hugged} | {self.text}"
class MiscCog(Cog, name="Divers"):
def __init__(self, bot: CustomBot):
self.bot = bot
self.show_hidden = False
self.verify_checks = True
self.computing = False
self.hugs = self.get_hugs()
@command(
name="choose",
@ -133,11 +160,45 @@ class MiscCog(Cog, name="Divers"):
async def pew(self, ctx):
await ctx.send("Tu t'es raté ! Kwaaack :duck:")
@command(aliases=["<3"])
async def hug(self, ctx, who="everyone"):
"""Fait un câlin à quelqu'un."""
@command(aliases=["pong"])
async def ping(self, ctx):
"""Affiche la latence avec le bot."""
msg: discord.Message = ctx.message
ping = msg.created_at.timestamp()
msg: discord.Message = await ctx.send("Pong !")
pong = time()
if who != "everyone":
# 7200 is because we are UTC+2
delta = pong - ping - 7200
await msg.edit(content=f"Pong ! Ça a pris {int(1000 * (delta))}ms")
@command(name="fan", aliases=["join", "adhere"], hidden=True)
async def fan_club_cmd(self, ctx: Context, who: Member):
"""Permet de rejoindre le fan-club d'Ananas ou Citron Vert."""
role_id = FAN_CLUBS.get(who.id, None)
role = get(ctx.guild.roles, id=role_id)
if role is not None:
await ctx.author.add_roles(role)
await ctx.send(f"Bienvenue au {role.mention} !! :tada:")
else:
await ctx.send(
f"{who.mention} n'a pas encore de fan club. Peut-être qu'un jour "
f"iel sera un membre influent du CNO ?"
)
# ----------------- Hugs ---------------- #
@command(aliases=["<3"])
async def hug(self, ctx: Context, who="everyone"):
"""Fait un câlin à quelqu'un. :heart:"""
if who == "everyone":
who = ctx.guild.default_role
elif who == "back":
return await self.hug_back(ctx)
else:
try:
who = await RoleConverter().convert(ctx, who)
except BadArgument:
@ -145,8 +206,6 @@ class MiscCog(Cog, name="Divers"):
who = await MemberConverter().convert(ctx, who)
except BadArgument:
return await ctx.send(f'Il n\'y a pas de "{who}". :man_shrugging:')
else:
who = ctx.guild.default_role
who: Union[discord.Role, Member]
bonuses = [
@ -168,6 +227,22 @@ class MiscCog(Cog, name="Divers"):
):
bonuses += ["Il s'agit surement là d'une tentative de corruption !"]
if has_role(ctx.author, Role.PRETRESSE_CALINS):
bonuses += [
"C'est le plus beau calin du monde :smiling_face_with_3_hearts: :smiling_face_with_3_hearts:",
]
if who.id == DIEGO:
bonuses += [
"Tiens... Ça sent le mojito... :lemon:",
":yellow_heart: :lemon: :yellow_heart:",
]
if (who.id == DIEGO and not get(ctx.author.roles, id=FAN_CLUBS[DIEGO])) or (
who.id == ANANAS and not get(ctx.author.roles, id=FAN_CLUBS[ANANAS])
):
bonuses += ["Tu devrais rejoindre son fan club :wink:"]
if who == ctx.author:
msg = f"{who.mention} se fait un auto-calin !"
bonuses += [
@ -184,6 +259,7 @@ class MiscCog(Cog, name="Divers"):
"Tout le monde est heureux maintenant !",
]
elif who == self.bot.user:
msg = f"{ctx.author.mention} me fait un gros câliiiiin !"
bonuses += ["Je trouve ça très bienveillant <3"]
else:
msg = f"{ctx.author.mention} fait un gros câlin à {who.mention} !"
@ -191,6 +267,7 @@ class MiscCog(Cog, name="Divers"):
f"Mais {who.mention} n'apprécie pas...",
"Et ils s'en vont chasser des canards ensemble :wink:",
"Oh ! Iel sent bon...",
"Et moi quand est ce que j'ai le droit à un calin ?",
f"{who.mention} a serré tellment fort qu'iel vous a coupé en deux :scream:",
f"{who.mention} propose à {ctx.author.mention} de se revoir autour d'une :pizza: !",
"Les drones du commissaire Winston passent par là et vous ordonnent d'arrêter.",
@ -200,32 +277,99 @@ class MiscCog(Cog, name="Divers"):
bonus = random.choice(bonuses)
await ctx.send(f"{msg} {bonus}")
text = f"{msg} {bonus}"
self.add_hug(ctx.author.id, who.id, text)
@command(aliases=["pong"])
async def ping(self, ctx):
"""Affiche la latence avec le bot."""
ping = time()
msg: discord.Message = await ctx.send("Pong !")
pong = time()
await ctx.send(text)
await msg.edit(content=f"Pong ! Ça a pris {int(1000 * (pong - ping))}ms")
async def hug_back(self, ctx: Context):
hugger = ctx.author.id
@command(name="fan", aliases=["join", "adhere"], hidden=True)
async def fan_club_cmd(self, ctx: Context, who: Member):
"""Permet de rejoindre le fan-club d'Ananas ou Citron Vert."""
role_id = FAN_CLUBS.get(who.id, None)
role = get(ctx.guild.roles, id=role_id)
if role is not None:
await ctx.author.add_roles(role)
await ctx.send(f"Bienvenue au {role.mention} !! :tada:")
else:
await ctx.send(
f"{who.mention} n'a pas encore de fan club. Peut-être qu'un jour "
f"iel sera un membre influent du CNO ?"
last_hug: Hug = get(reversed(self.hugs), hugged=hugger)
if not last_hug:
return await ctx.send(
f"Personne n'a jamais fait de calin à {ctx.author.mention}, il faut y remédier !"
)
if "coupé en deux" in last_hug.text:
return await ctx.send(
"Tu ne vas quand même pas faire un câlin à quelqu'un "
"que tu viens de couper en deux !"
)
await ctx.invoke(self.hug, str(last_hug.hugger))
@command(name="hug-stats")
@commands.has_role(Role.PRETRESSE_CALINS)
async def hugs_stats_cmd(self, ctx: Context):
medals = [
":first_place:",
":second_place:",
":third_place:",
":medal:",
":military_medal:",
]
ranks = ["Gros Nounours", "Petit Panda", "Ours en peluche"]
embed = discord.Embed(
title="Prix du plus câliné", color=discord.Colour.magenta(),
)
stats = Counter()
for h in self.hugs:
if h.hugged != h.hugger:
stats[h.hugged] += 1
top = stats.most_common(15)
for i in range(3):
m = medals[i]
r = ranks[i]
id, qte = top[i]
who = self.name_for(ctx, id)
embed.add_field(name=f"{m} - {r}", value=f"{who} : {qte} :heart:")
top4to7 = "\n ".join(
f"{medals[3]} {self.name_for(ctx, id)} : {qte} :orange_heart:"
for id, qte in top[3:8]
)
embed.add_field(name="Apprentis peluches", value=top4to7)
top8to13 = "\n".join(
f"{medals[4]} {self.name_for(ctx, id)} : {qte} :yellow_heart:"
for id, qte in top[8:13]
)
embed.add_field(name="Pelotte de laine", value=top8to13)
await ctx.send(embed=embed)
def name_for(self, ctx, member_or_role_id):
memb = ctx.guild.get_member(member_or_role_id)
if memb is not None:
name = memb.mention
else:
name = ctx.guild.get_role(member_or_role_id).mention
return name
def hugger_tot(self, hugger: int):
return sum(1 for h in self.hugs if h.hugger == hugger)
def hugged_tot(self, hugged: int):
return sum(1 for h in self.hugs if h.hugged == hugged)
def get_hugs(self):
File.HUGS.touch()
lines = File.HUGS.read_text().strip().splitlines()
return [Hug.from_str(l) for l in lines]
def add_hug(self, hugger: int, hugged: int, text):
File.HUGS.touch()
with open(File.HUGS, "a") as f:
f.write(f"{hugger} -> {hugged} | {text}\n")
self.hugs.append(Hug(hugger, hugged, text))
# ---------------- Jokes ---------------- #
def load_jokes(self) -> List[Joke]:
@ -242,13 +386,13 @@ class MiscCog(Cog, name="Divers"):
yaml.safe_dump_all(jokes, f)
@group(name="joke", invoke_without_command=True)
async def joke(self, ctx: Context, id: int = None):
async def joke(self, ctx: Context):
m: discord.Message = ctx.message
await m.delete()
jokes = self.load_jokes()
if id is not None:
if False:
joke_id = id
jokes = sorted(
jokes, key=lambda j: len(j.likes) - len(j.dislikes), reverse=True
@ -290,6 +434,8 @@ class MiscCog(Cog, name="Divers"):
file: discord.Attachment = message.attachments[0]
joke.file = str(f"{joke_id}-{file.filename}")
await file.save(File.MEMES / joke.file)
elif not msg.strip():
return "Tu ne peux pas ajouter une blague vide..."
jokes.append(joke)
self.save_jokes(jokes)
@ -306,7 +452,7 @@ class MiscCog(Cog, name="Divers"):
)
start = time()
end = start + 24 * 60 * 60
end = start + 24 * 60 * 60 * 5 # 5 days
while time() < end:
try:
@ -327,7 +473,7 @@ class MiscCog(Cog, name="Divers"):
self.save_jokes(jokes)
@joke.command(name="top", hidden=True)
@joke.command(name="top", hidden=True, enabled=False)
async def best_jokes(self, ctx: Context):
"""Affiche le palmares des blagues."""

View File

@ -71,6 +71,7 @@ class Role:
CAPTAIN = "Capitaine"
PARTICIPANT = "Participant"
TOURIST = "Touriste"
PRETRESSE_CALINS = "Grande prêtresse des câlins"
class Emoji:
@ -90,6 +91,7 @@ class File:
JOKES = TOP_LEVEL / "data" / "jokes"
JOKES_V2 = TOP_LEVEL / "data" / "jokesv2"
MEMES = TOP_LEVEL / "data" / "memes"
HUGS = TOP_LEVEL / "data" / "hugs"
with open(File.TOP_LEVEL / "data" / "problems") as f:

View File

@ -1,4 +1,5 @@
from functools import wraps
from typing import Union
import psutil
from discord.ext.commands import Bot
@ -17,10 +18,13 @@ def french_join(l):
return f"{start} et {l[-1]}"
def has_role(member, role: str):
def has_role(member, role: Union[str, tuple]):
"""Return whether the member has a role with this name."""
return any(r.name == role for r in member.roles)
if isinstance(role, str):
return any(r.name == role for r in member.roles)
else:
return any(r.name == rol for r in member.roles for rol in role)
def send_and_bin(f):