77
88import discord
99from redbot .core import Config , bank , checks , commands
10+ from redbot .core .bot import Red
1011from redbot .core .errors import BalanceTooHigh
1112from redbot .core .utils .chat_formatting import (
1213 bold ,
1819from redbot .core .utils .menus import DEFAULT_CONTROLS , menu
1920from redbot .core .utils .predicates import MessagePredicate
2021
21- __version__ = "3.4.12 "
22+ __version__ = "3.5.0 "
2223log = logging .getLogger ("red.vrt.hunting" )
2324
2425
@@ -35,7 +36,7 @@ async def red_delete_data_for_user(
3536
3637 def __init__ (self , bot , * args , ** kwargs ):
3738 super ().__init__ (* args , ** kwargs )
38- self .bot = bot
39+ self .bot : Red = bot
3940 self .config = Config .get_conf (self , 2784481002 , force_registration = True )
4041
4142 self .animals = {
@@ -389,59 +390,82 @@ async def do_tha_bang(
389390 self .in_game .discard (channel .id )
390391
391392 async def _wait_for_bang (self , guild : discord .Guild , channel : discord .TextChannel , conf : dict ):
392- def mcheck (m : discord .Message ):
393- if m .guild != guild :
394- return False
395- if m .channel != channel :
396- return False
397- if not m .content :
398- return False
399- res = m .content .lower ().strip ()
400- return "bang" in res
393+ bang = ["💥" , "\N{COLLISION SYMBOL} " ]
394+ salute = ["🫡" , "\N{SALUTING FACE} " ]
395+ animal = random .choice (list (self .animals .keys ()))
396+ await channel .send (self .animals [animal ])
401397
402- def rcheck ( r : discord .Reaction , u : discord . Member ):
403- if u . bot :
398+ def bang_mcheck ( m : discord .Message ):
399+ if m . guild != guild or m . channel != channel or not m . content :
404400 return False
405- if r .message .guild != guild :
406- return False
407- if r .message .channel != channel :
401+ return "bang" in m .content .lower ().strip ()
402+
403+ def salute_mcheck (m : discord .Message ):
404+ if m .guild != guild or m .channel != channel or not m .content :
408405 return False
409- if not u :
406+ return any (s in m .content .lower ().strip () for s in salute )
407+
408+ def bang_rcheck (r : discord .Reaction , u : discord .Member ):
409+ if u .bot or r .message .guild != guild or r .message .channel != channel :
410410 return False
411- return str (r .emoji ) == "💥"
411+ return str (r .emoji ) in bang
412412
413- animal = random .choice (list (self .animals .keys ()))
413+ def salute_rcheck (r : discord .Reaction , u : discord .Member ):
414+ if u .bot or r .message .guild != guild or r .message .channel != channel :
415+ return False
416+ return str (r .emoji ) in salute
414417
415- animal_message = await channel .send (self .animals [animal ])
416418 now = datetime .now ().timestamp ()
417419 timeout = conf ["wait_for_bang_timeout" ]
420+ # Wait for whatever comes first, a message with bang or a reaction with bang emoji
421+ # Use asyncio.FIRST_COMPLETED to return the first completed future
422+ futures : list [asyncio .Future ] = []
423+ futures .append (asyncio .ensure_future (self .bot .wait_for ("message" , check = bang_mcheck , timeout = timeout )))
424+ futures .append (asyncio .ensure_future (self .bot .wait_for ("reaction_add" , check = bang_rcheck , timeout = timeout )))
425+ if animal == "eagle" :
426+ futures .append (asyncio .ensure_future (self .bot .wait_for ("message" , check = salute_mcheck , timeout = timeout )))
427+ futures .append (
428+ asyncio .ensure_future (self .bot .wait_for ("reaction_add" , check = salute_rcheck , timeout = timeout ))
429+ )
418430
419- if conf ["bang_words" ]:
420- try :
421- bang_msg = await self .bot .wait_for ("message" , check = mcheck , timeout = timeout )
422- except asyncio .TimeoutError :
423- return await channel .send (f"The { animal } got away!" )
424- author = bang_msg .author
431+ done , pending = await asyncio .wait (futures , return_when = asyncio .FIRST_COMPLETED )
432+ for future in pending :
433+ future .cancel ()
434+ res = done .pop ().result ()
435+ if isinstance (res , discord .Message ):
436+ author : discord .Member = res .author
437+ saluted = False
438+ if any (s in res .content .lower ().strip () for s in salute ) and animal == "eagle" :
439+ saluted = True
425440 else :
426- emoji = "\N{COLLISION SYMBOL} "
427- await animal_message .add_reaction (emoji )
428- try :
429- reaction , author = await self .bot .wait_for ("reaction_add" , check = rcheck , timeout = timeout )
430- except asyncio .TimeoutError :
431- return await channel .send (f"The { animal } got away!" )
441+ reaction : discord .Reaction = res [0 ]
442+ author : discord .Member = res [1 ]
443+ saluted = False
444+ if str (reaction .emoji ) in salute and animal == "eagle" :
445+ saluted = True
432446
433447 bang_now = datetime .now ().timestamp ()
434448 time_for_bang = round (bang_now - now , 1 )
435449 bangtime = "" if not await self .config .guild (guild ).bang_time () else f" in { time_for_bang } s"
436450
437451 if random .randrange (0 , 17 ) > 1 :
438- if conf ["eagle" ] and animal == "eagle" :
439- punish = await self .maybe_send_reward (guild , author , True )
440- if punish :
441- cur_name = await bank .get_currency_name (guild )
442- msg = f"Oh no! { author .display_name } shot an eagle{ bangtime } and paid { punish } { cur_name } in fines!"
452+ if animal == "eagle" and conf ["eagle" ]:
453+ # Shooting bad, salute good
454+ if saluted :
455+ await self .add_score (author , animal )
456+ reward = await self .maybe_send_reward (guild , author )
457+ if reward :
458+ cur_name = await bank .get_currency_name (guild )
459+ msg = f"{ author .display_name } saluted the eagle{ bangtime } and earned { reward } { cur_name } !"
460+ else :
461+ msg = f"{ author .display_name } saluted the eagle{ bangtime } !"
443462 else :
444- msg = f"Oh no! { author .display_name } shot an eagle{ bangtime } !"
463+ punish = await self .maybe_send_reward (guild , author , True )
464+ if punish :
465+ cur_name = await bank .get_currency_name (guild )
466+ msg = f"Oh no! { author .display_name } shot an eagle{ bangtime } and paid { punish } { cur_name } in fines!"
467+ else :
468+ msg = f"Oh no! { author .display_name } shot an eagle{ bangtime } !"
445469 else :
446470 await self .add_score (author , animal )
447471 reward = await self .maybe_send_reward (guild , author )
@@ -452,6 +476,8 @@ def rcheck(r: discord.Reaction, u: discord.Member):
452476 msg = f"{ author .display_name } shot a { animal } { bangtime } !"
453477 else :
454478 msg = f"{ author .display_name } missed the shot and the { animal } got away!"
479+ if conf ["eagle" ] and animal == "eagle" and saluted :
480+ msg = f"{ author .display_name } saluted the eagle but it just flew away!"
455481
456482 await channel .send (bold (msg ))
457483
0 commit comments