+
    ;>j_                        R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIH	t	 ^ RI
Ht ]P                  P                  RR4      tRRR	utttR
Rutt]! ]P                  P                  RR4      4      t]! ]P                  P                  RR4      4      t]! ]P                  P                  RR4      4      tRsR tR tR tR tR tR tR4R lt R t!R t"R t#R t$R t%R t&R t'R  t(R! t)R" t* ! R# R$]PV                  PX                  ]PV                  PZ                  ,          R%R&7      t. ! R' R(]PV                  PX                  ]PV                  PZ                  ,          R)R&7      t/R* t0 ! R+ R,]PV                  Pb                  4      t2 ! R- R.]PV                  Pb                  4      t3 ! R/ R0]PV                  Pb                  4      t4 ! R1 R2]	Pj                  4      t6R3 t7R# )5u  Timer/Elo feature — a motivational commitment-timer. discord.py **extension** (a Cog) loaded by
handler.py into the shared bot. NOT run standalone. See TIMER_BOT_SPEC.md and SERVER_SETUP.md.

Minimal surface: ONE command, `/meta`. It opens an ephemeral panel (your rating + streak) →
pick a task from the ladder → pick a preset commit-time → the bomb arms (public message + Defuse
button). One Defuse click inside the window [started+band_lo, started+YY] = SUCCESS (user↑/task↓), no modal;
no defuse by close = DETONATE = FAIL (the only push the bot makes). On success a frictionless
'continue' (reopens the panel) vs 10s-cooldown 'stop' fork nudges momentum — no rating effect.
Pure human-vs-task Glicko (reuses glicko2.update_match). Streak is cosmetic: +1 on defuse, reset on detonate.

Env: TIMER_DB (merged deploy: /opt/korean-bot/timer.db), TIME_UNIT (real seconds per "minute";
lower = test mode), STOP_COOLDOWN.
N)app_commands)commands)update_matchTIMER_DBz/opt/timer-bot/timer.dbg     @g     u@gQ?g      ?g333333?STOP_REVEAL10	AUTO_META15	TIME_UNIT60c                  d    \         P                  ! \        4      p \         P                  V n        V # N)sqlite3connectr   Rowrow_factory)cons    /tmp/timer_bot.py_dbr      s     
//(
#CkkCOJ    c                    V P                  R V34      P                  4       pV'       d   \        V4      # \        P                  P	                  \        P
                  4      P                  4       pV P                  RV\        \        \        V34       V P                  4        \        V P                  R V34      P                  4       4      # )z#SELECT * FROM users WHERE user_id=?zEINSERT INTO users(user_id,rating,rd,vol,created_at) VALUES(?,?,?,?,?))executefetchonedictdatetimenowUTC	isoformat
USER_STARTUSER_RDVOLcommit)r   uidrr   s   &&  r   	_get_userr$   %   s    9C6BKKMAAw





-
7
7
9CKKWj'346JJLAC6JSSUVVr   c                      \        4       p V P                  R 4       Uu. uF  p\        V4      NK  	  ppV P                  4        V# u upi )z9SELECT * FROM tasks WHERE status='active' ORDER BY ratingr   r   r   closer   r#   rowss      r   list_tasks_syncr*   0   sP    
%C [[CE F EDG ED FIIKKF   Ac                ,    \        V 4      \        4       3# )zLEverything the /meta panel needs in one hop: the user row + the task ladder.)
stats_syncr*   )r"   s   &r   meta_data_syncr.   8   s    c?O---r   c                    \        4       p\        WP4       VP                  R V34      P                  4       pV'       g   VP	                  4        R	# VR,          Tu;8:  d   VR,          8:  g0   M VP	                  4        RRVR,          VR,          VR,          33# \
        P
                  ! 4       pWvR,          \        ,          ,           pWt\        ,          ,           p	VP                  RWW#WxW34      p
VP                  4        V
P                  p\        VP                  RV34      P                  4       4      pVR,          VR&   VP	                  4        VR3# )
z7SELECT * FROM tasks WHERE task_no=? AND status='active'Nband_lo_minband_hi_minbandnamezINSERT INTO timers(user_id,guild_id,channel_id,task_no,started_ts,open_ts,close_ts,yy_min,state) VALUES(?,?,?,?,?,?,?,?,'running')SELECT * FROM timers WHERE id=?	task_name)Ntask_not_found)
r   r$   r   r   r'   timer
   r!   	lastrowidr   )r"   gid
channel_idtask_noyy_minr   tr   open_tsclose_tscurtidrows   &&&&&        r   create_timer_syncrC   =   s"   
%CcMPWzZcceA		%%m:!M*::		fa.-0@!F)LLL
))+Cm$y00Gi''H
++	-	:hGIC JJL
--C
s{{<sfENNP
QCyCIIK9r   c                     \        4       pVP                  R W34       VP                  4        VP                  4        R# )z)UPDATE timers SET message_id=? WHERE id=?N)r   r   r!   r'   )rA   
message_idr   s   && r   set_message_syncrF   V   s-    
%CKK;j=NOJJLIIKr   c                ~   V'       d   RMTpV P                  RWaR,          34      pVP                  ^ 8X  d   R# VR,          VR,          r\        W4      p
\        V P                  RV	34      P	                  4       4      pV'       d   RMR	p\        R
V
R
,          RV
R,          RV
R,          /R
VR
,          RVR,          RVR,          /V\        \        4      w  w  rpw  pppV'       d   V P                  RWW34       MV P                  RWW34       VR,          pV'       d0   Ve,   VR,          f   TMRVR,          ,          RV,          ,           pV P                  RVVVVV	34       \        P                  P                  \        P                  4      P                  4       pV'       d0   V P                  R\        P                  ! 4       W4VR,          34       T P                  RYVR,          V'       d   ^M^ VV34       V P                  4        RVR,          RV
R
,          RVRVRVR,          RVR,          /# )a  Guarded resolution: atomically claim the running->terminal transition, then Glicko-update
user and task. Returns dict for messaging, or None if the timer was already resolved.
fail_state distinguishes a passive 'detonated' from a voluntary 'abandoned' (same rating cost).donez8UPDATE timers SET state=? WHERE id=? AND state='running'idNuser_idr;   z#SELECT * FROM tasks WHERE task_no=?g      ?g        ratingrdvolzUPDATE users SET rating=?,rd=?,vol=?,n_attempts=n_attempts+1,n_success=n_success+1,meta_streak=meta_streak+1,meta_best=MAX(meta_best,meta_streak+1) WHERE user_id=?zZUPDATE users SET rating=?,rd=?,vol=?,n_attempts=n_attempts+1,meta_streak=0 WHERE user_id=?ref_time_ming?g?z[UPDATE tasks SET rating=?,rd=?,vol=?,n_attempts=n_attempts+1,ref_time_min=? WHERE task_no=?z@UPDATE timers SET reported_ts=?,reported_min=?,note=? WHERE id=?zZINSERT INTO attempts(user_id,task_no,timer_id,success,reported_min,ts) VALUES(?,?,?,?,?,?)r5   r3   oldnewstater:   rE   )r   rowcountr$   r   r   r   TAU_USERTAU_TASKr   r   r   r   r7   r!   )r   timersuccessreported_minnote
fail_state	new_stater@   r"   r;   ur=   scoreururduvtrtrdtvnew_refnow_isos   &&&&&&               r   _apply_matchre   ]   s    "zI
++PS\dh^iRj
kC
||q#U9%5#AS[[>
KTTVWACE#/	1X;aguah?	1X;aguah?RZ$\ MRb=BR  gb&	(
 	pb&	(G<+"#N"3";,qGXAX[^am[mAmKKmS"gw/1##HLL1;;=GVYY[,eDkB	DKKluT{AawWYJJL6E1X;r7I%-|U<=PR Rr   c                     \        4       pVP                  R V 34      P                  4       pV'       g   VP                  4        R# \	        V\        V4      RW4      pVP                  4        V# )r4   NTr   r   r   r'   re   r   )rA   rW   rX   r   rU   outs   &&&   r   resolve_success_syncri      sV    
%CKK9C6BKKME		
sDK|
BCIIKJr   c                     \        4       pVP                  R V 34      P                  4       pV'       g   VP                  4        R# \	        V\        V4      R4      pVP                  4        V# )r4   NFrg   rA   r   rU   rh   s   &   r   resolve_detonate_syncrl      sT    
%CKK9C6BKKME		
sDK
/CIIKJr   c                     \        4       pVP                  R V 34      P                  4       pV'       g   VP                  4        R# \	        V\        V4      RRR7      pVP                  4        V# )r4   NF	abandoned)rY   rg   rk   s   &   r   resolve_abandon_syncro      sV    
%CKK9C6BKKME		
sDK;
GCIIKJr   c                      \        4       p V P                  R 4       Uu. uF  p\        V4      NK  	  ppV P                  4        V# u upi )z*SELECT * FROM timers WHERE state='running'r&   r(   s      r   get_running_timers_syncrq      sA    
%C [[)UVWVDGVDWIIKK Xr+   c                 P    \        4       p\        W4      pVP                  4        V# r   )r   r$   r'   )r"   r   r[   s   &  r   r-   r-      s!    
%C#AIIKHr   c                     \        4       pVP                  R V 34      P                  4       pVP                  4        V'       d   \	        V4      # R# )r4   N)r   r   r   r'   r   )rA   r   r#   s   &  r   get_timer_syncrt      s?    
%C5v>GGIAIIK47!T!r   c           	      R    W8  d   R MRpV R RVR RV \        W,
          4      R 2# )u   🟢▲u   🔴▼.0fu    → **z**  )abs)rO   rP   arrows   && r   	fmt_deltary      s5    IE#Ygc#Yd5'#ci.1EFFr   c                   a a SS 8:  d   S.# S \        ^\        SS ,
          ^,          4      4      ,           \        S S,           ^,          4      S0p\        VV 3R lV 4       4      ;'       g    S.# )zZUp to 3 commit-time presets within (lo, hi]. YY must exceed band_lo for a non-zero window.c              3   R   <"   T F  pSTu;8  d
   S8:  g   K  M K  Vx  K  	  R # 5ir    ).0chilos   & r   	<genexpr>preset_times.<locals>.<genexpr>   s     1SBLbL!L!Ss   ''
')maxroundsorted)r   r   raws   ff r   preset_timesr      s^    	RxtAub2g]+,,eR"WM.BB
GC1S1199bT9r   c                    VR ,          '       d   VR,          VR ,          ,          ^d,          M^ p\         P                  ! RRRR7      pVP                  RVR,          R R	^VR
,          ,          R 2RR7       VP                  RVR,           RVR,           R2RR7       VP                  RVR ,           RVR R2RR7       V# )
n_attempts	n_successu"   🔥 Meta — what will you start?z3Pick a task, arm it, and defuse it before it blows.\ )titledescriptioncolorRatingrK   rv   u    · ±rL   Tr3   valueinlineu   🔥 Streakmeta_streakz (best 	meta_best)Record    · z	% success)discordEmbed	add_field)r3   r[   acces   &&  r   meta_panel_embedr      s    67oo1[>AlO+c11C@"W_g	iAKKX(C'8q1T7{3>O%PY]K^KK]Q}-=,>ganEUUV*W`dKeKKX,'8SIY%OX\K]Hr   c                     \         P                  ! R V R,           2RRV R,          R RV R,           RV R	,           R
2R7      pV# )u   🧨 r3   r   zDifficulty **rK   rv   u   ** · valid band r0      –r1   zm
How long do you commit?r   r   r   )r   r   )r=   r   s   & r   task_pick_embedr      sX    eAfI;/x%21X;s2CCT%&}%5$6c!M:J9KKe$g	iA Hr   c                   T   a a ] tR t^t oV3R lV 3R llt]R 4       tR tRtVt	V ;t
# )DefuseButtonc                    < V ^8  d   QhRS[ /#    timer_idint)format__classdict__s   "r   __annotate__DefuseButton.__annotate__   s     M M Mr   c                   < Wn         \        SV `	  \        P                  P                  R \        P                  P                  RV 2R7      4       R# )u   🧨 Defusezdefuse:labelstyle	custom_idN)r   super__init__r   uiButtonButtonStyledangerselfr   	__class__s   &&r   r   DefuseButton.__init__   sG     **gFYFYF`F`8?z6J + L 	Mr   c               :   "   V ! \        VR ,          4      4      # 5irA   r   clsinteractionitemmatchs   """"r   from_custom_idDefuseButton.from_custom_id        3uU|$%%   c                |   "   \         '       d*   \         P                  WP                  4      G R j  xL
  R # R #  L5ir   )_COGhandle_defuser   r   r   s   &&r   callbackDefuseButton.callback   s*     4$$[--@@@ @   /<:	<r   __name__
__module____qualname____firstlineno__r   classmethodr   r   __static_attributes____classdictcell____classcell__r   r   s   @@r   r   r      s1     M M
 & &A Ar   r   zdefuse:(?P<tid>\d+))templatec                   T   a a ] tR t^t oV3R lV 3R llt]R 4       tR tRtVt	V ;t
# )AbandonButtonc                    < V ^8  d   QhRS[ /# r   r   )r   r   s   "r   r   AbandonButton.__annotate__   s     N N Nr   c                   < Wn         \        SV `	  \        P                  P                  R \        P                  P                  RV 2R7      4       R# )u   🏳️ Abandonzabandon:r   N)r   r   r   r   r   r   r   	secondaryr   s   &&r   r   AbandonButton.__init__   sH     **1B'J]J]JgJg8@
6K + M 	Nr   c               :   "   V ! \        VR ,          4      4      # 5ir   r   r   s   """"r   r   AbandonButton.from_custom_id   r   r   c                |   "   \         '       d*   \         P                  WP                  4      G R j  xL
  R # R #  L5ir   )r   handle_abandonr   r   s   &&r   r   AbandonButton.callback   s*     4%%k==AAA Ar   r   r   r   s   @@r   r   r      s1     N N
 & &B Br   r   zabandon:(?P<tid>\d+)c                     \         P                  P                  R R7      pVP                  \	        V 4      4       VP                  \        V 4      4       V# )Ntimeout)r   r   Viewadd_itemr   r   )r   vs   & r   
armed_viewr      s=    

%AJJ|H%&JJ}X&'Hr   c                   T   a a ] tR tRt oRtV 3R ltR tR tR tR t	R t
R	tVtV ;t# )
ContinueStopViewi  u   Post-defuse momentum fork, 3 phases:
0–STOP_REVEAL      : only '🔥 keep going' (you can't quit on reflex)
STOP_REVEAL–AUTO_META : '✓ stop' also appears
AUTO_META          : auto-reopens the panel — so IGNORE = continue, never a free stop.c                  < \         SV `  R R7       WVuV n        V n        V n        RV n        RV n        \        P                  ! 4       \        ,           V n	        \        P                  ! 4       \        ,           V n        \        P                  P                  R\        P                  P                   R7      V n        V P$                  V P"                  n        \        P                  P                  R\        P                  P(                  R7      V n        V P,                  V P*                  n        V P/                  V P"                  4       R# ),  r   FNu   🔥 Keep going (new meta)r   r   u   ✓ Stop)r   r   cogr"   rh   rH   _taskr7   r   stop_atr   auto_atr   r   r   r   rV   flameon_flamer   r   stopon_stopr   )r   r   r"   rh   r   s   &&&&r   r   ContinueStopView.__init__  s    %'*$$(DH	
yy{[0yy{Y.ZZ&&-IQXQdQdQlQl&m
"mm

JJ%%Jg>Q>Q>[>[%\	!\\		djj!r   c                   \         P                  ! R RRV P                  R,           R2R7      pVP                  R\	        V P                  R,          V P                  R,          4      R	R
7       \
        P
                  P                  V P                  \
        P                  4      pVR8X  d~   \
        P
                  P                  V P                  \
        P                  4      pR\         P                  P                  VR4       R\         P                  P                  VR4       2pM#R\         P                  P                  VR4       2pVP                  RVR	R
7       V# )   ✅ DefusediW **r5   u   ** — nailed it.r   r   rO   rP   Fr   lockedu   🔒 stop unlocks Ru    · 🔥 auto-continues u$   ✓ stop now · 🔥 auto-continues u   ​)r   r   rh   r   ry   r   fromtimestampr   r   r   utils	format_dt)r   phaser   auto_dtstop_dttails   &&    r   embedContinueStopView.embed  s   MMX(*488K+@*AAR&SU	488E?DHHUO)T]bc##11$,,MH''55dllHLLQG()@)@#)N(O P++2==+B+B7C+P*QSD :'--:Q:QRY[^:_9`aD	d59r   c                X   a a VV 3R  lp\         P                  ! V! 4       4      S n        R# )c                    <"    \         P                  ! \        4      G R j  xL
  SP                  '       d   R # SP	                  SP
                  4       SP                  SP                  R4      SR7      G R j  xL
  \         P                  ! \        ^ \        \        ,
          4      4      G R j  xL
  SP                  '       d   R # RSn        SP                   F
  p RV n        K  	  SP                  RR SR7      G R j  xL
  SP                  P                  SRR7      G R j  xL
  R #  EL L L L2 L  \         P                  \        3 d     R # i ; i5i)Nopenr  viewTu&   🔥 Kept the flame — next one's up.contentr  r  followup)asynciosleepr   rH   r   r   edit_original_responser  r   r   childrendisabledr   	open_metaCancelledError	Exception)r~   r   r   s    r   run#ContinueStopView.start.<locals>.run"  s    mmK000999dii(!88tzz&?QX\8]]]mmC9{+B$CDDD999 	A!%AJ '!88DDW[ 9 ] ] ]hh((t(DDD 1 ^D]D**I6 s   ED: D/D: EA D: ;D2<6D: 2D43D: 	E8D: D6$D: (D8)D: -E/D: 2D: 4D: 6D: 8D: :EEEEN)r  create_taskr   )r   r   r  s   ff r   startContinueStopView.start!  s    	$ ((/
r   c                    R V n         V P                  '       d   V P                  P                  4        V P                   F
  pR Vn        K  	  R# )TN)rH   r   cancelr  r  )r   r~   s   & r   _finishContinueStopView._finish6  s7    	:::JJAAJ r   c                8  "   V P                   '       d%   VP                  P                  4       G R j  xL
  R # V P                  4        VP                  P	                  V R7      G R j  xL
  V P
                  P                  VRR7      G R j  xL
  R #  La L- L
5i)N)r  Tr  )rH   responsedeferr"  edit_messager   r  r   s   &&r   r   ContinueStopView.on_flame=  sy     999&&,,...""//T/:::hh  t <<<	 / 	;<s3   0BB5B(B)$BBBBBc                   "   V P                   '       d%   VP                  P                  4       G R j  xL
  R # V P                  4        VP                  P	                  RR V R7      G R j  xL
  R #  L> L5i)Nu1   🔥 Stopped. Call `/meta` when you need a spark.r  )rH   r%  r&  r"  r'  r   s   &&r   r   ContinueStopView.on_stopE  sk     999&&,,...""//GtZ^ 0 ` 	` 	` /	`s!   0A5A17A5*A3+A53A5)	r   r   r   rH   r   rh   r   r   r"   )r   r   r   r   __doc__r   r  r  r"  r   r   r   r   r   r   s   @@r   r   r     s0     b"0*=` `r   r   c                   8   a a ] tR tRt oV 3R ltR tRtVtV ;t# )MetaViewiO  c                H  < \         SV `  R R7       Wn        V Uu/ uF  p\        VR,          4      VbK  	  upV n        VR,           Uu. uFi  p\
        P                  ! VR,          R,          VR,          R RVR	,           R
VR,           RVR,           2R,          \        VR,          4      R7      NKk  	  pp\
        P                  P                  RVR7      V n	        V P                  V P                  n        V P                  V P                  4       R# u upi u upi )r   r   r;   :N   Nr3   :Nd   NrK   rv   r   r0   r   r1   u   m · domain)r   r   r   u   Pick a task to start…)placeholderoptionsN)r   r   r   strtasksr   SelectOptionr   Selectselon_pickr   r   )r   r   r5  r=   optsr   s   &&&  r   r   MetaView.__init__P  s   %49:Eqc!I,'*E:
 7<CjB 7A $$F)D/#$X;s"34-8H7IQ}M]L^^cdefndocp qrv wa	l+- 7A 	 B ::$$1JTX$Y LLdhh ;Bs   DA/Dc                   "   V P                   V P                  P                  ^ ,          ,          pVP                  P	                  \        V4      \        V P                  V4      R7      G Rj  xL
  R#  L5i)    r  N)r5  r8  valuesr%  r'  r   TimePickViewr   )r   r   r=   s   && r   r9  MetaView.on_pick\  sS     JJtxxq)*""//oa6H|\`\d\dfgOh/iiis   A,A7.A5/A7)r   r8  r5  )	r   r   r   r   r   r9  r   r   r   r   s   @@r   r-  r-  O  s     
 j jr   r-  c                   >   a a ] tR tRt oV 3R ltR tR tRtVtV ;t	# )r?  ia  c                  < \         SV `  R R7       WuV n        V n        \	        VR,          VR,          4       Ff  p\
        P                  P                  V R2\
        P                  P                  R7      pV P                  V4      Vn        V P                  V4       Kh  	  \
        P                  P                  R\
        P                  P                  R7      pV P                  Vn        V P                  V4       R# )r   r   r0   r1   mr   u   ↩ backN)r   r   r   r=   r   r   r   r   r   primary_mkr   r   r   on_back)r   r   r=   yybbackr   s   &&&   r   r   TimePickView.__init__b  s    %$&q/=1ABB

!!2$a8K8K8S8S!TA"AJMM! C zz  z9L9L9V9V Wdr   c                   a a V V3R  lpV# )c                    <"   SP                   P                  V SP                  R ,          S4      G Rj  xL
  R#  L5i)r;   N)r   	arm_timerr=   )r   r   rG  s   &r   cbTimePickView._mk.<locals>.cbn  s+     (($$[$&&2CRHHHs   2><>r|   )r   rG  rN  s   ff r   rE  TimePickView._mkm  s    	I	r   c                H  "   \         P                  ! \        \        VP                  P
                  4      4      G R j  xL
 w  r#VP                  P                  \        VP                  P                  V4      \        V P                  V4      R7      G R j  xL
  R #  L_ L5i)Nr  )r  	to_threadr.   r4  userrI   r%  r'  r   display_namer-  r   )r   r   r[   r5  s   &&  r   rF  TimePickView.on_backr  s      **>3{?O?O?R?R;STT""//";#3#3#@#@!D8TXT\T\^cKd 0 f 	f 	f U	fs"   <B"BAB"B B" B")r   r=   )
r   r   r   r   r   rE  rF  r   r   r   r   s   @@r   r?  r?  a  s     	
f fr   r?  c                      a  ] tR tRt o R tR tR tR tR tR t	R t
R	 tR
 tR tRR lt]P                   ! RRR7      R 4       tRtV tR# )TimerCogiy  c                    Wn         / V n        V s\        P                  ! 4       P                  V P                  4       4       R # r   )botpendingr   r  get_running_loopr  _startup)r   rY  s   &&r   r   TimerCog.__init__z  s0      "..t}}?r   c                r    V P                   P                  VR 4      pV'       d   VP                  4        R # R # r   )rZ  popr!  )r   rA   tasks   && r   cancel_pendingTimerCog.cancel_pending  s)    ||T*KKM r   c                    V P                  V4       \        P                  ! V P                  W4      4      V P                  V&   R # r   )ra  r  r  _detonate_afterrZ  )r   rA   r?   s   &&&r   schedule_detonationTimerCog.schedule_detonation  s4    C #//0D0DS0STSr   c                  "    \         P                  ! \        ^ V\        P                  ! 4       ,
          4      4      G Rj  xL
  \         P
                  ! \        T4      G Rj  xL
 pT P                  P                  TR4       T'       d   T P                  T4      G Rj  xL
  R# R#  Lh  \         P                   d     R# i ; i Lc L(5i)r=  N)
r  r  r   r7   r  rR  rl   rZ  r_  _post_detonation)r   rA   r?   rh   s   &&& r   rd  TimerCog._detonate_after  s     	--Ax$))+'= >??? %%&;SAAd#'',,,  @%% 		A -s^   C=B, B*B, C$C%'CC!C
"C*B, ,CCCC
Cc                  "   V P                  V4      G R j  xL
  VP                  R4      '       d,   V P                  P                  \	        VR,          4      4      MR pV'       dn   \
        P                  ! RRRVR,           R2R7      pVP                  R\        VR	,          VR
,          4      RR7        VP                  VR7      G R j  xL
  R # R #  L L
  \         d     R # i ; i5i)Nr:      💥 DetonatediEB r   r5   u!   ** — you didn't defuse in time.r   r   rO   rP   Fr   )r  )mark_message_donegetrY  get_channelr   r   r   r   ry   sendr  )r   rh   chr   s   &&  r   rh  TimerCog._post_detonation  s     $$S)))=@WW\=R=RTXX!!#c,&7"89X\$4H,.s;/?.@@a*bdAKKXYs5z3u:-NW\K]ggAg&&&  	* ' sQ   C-CC-4C-(AC-9C CC C-C C*&C-)C**C-c                  "   VP                  R4      '       d   VP                  R4      '       g   R# V P                  P                  \        VR,          4      4      pV'       g   R# RRRRRR	/P                  VP                  R
4      R4      p VP	                  \        VR,          4      4      pVP                  V RVR,           R2RRR7      G Rj  xL
  R#  L  \         d     R# i ; i5i)zLBest-effort edit of the original public timer message to its terminal state.r:   rE   NrH   r   rn      🏳️ Abandoned	detonatedrk  rQ   u	   • endedu    · **r5   r   r  )rm  rY  rn  r   get_partial_messageeditr  )r   rh   rp  tagmsgs   &&   r   rl  TimerCog.mark_message_done  s     ww|$$CGGL,A,AXX!!#c,&7"89}k3F,..1c#'''2BK.P 		((S->)?@C((cU&[1A0B"#ETX\(]]] 		sB   .C0AC0AC CC C0C C-)C0,C--C0c                  "    V P                   P                  4       G R j  xL
  \        P                  ! \
        4      G R j  xL
  F  p\        P                  ! 4       TR,          8  dP   \        P                  ! \        TR,          4      G R j  xL
 pT'       d   T P                  T4      G R j  xL
  Kq  Ks  T P                  TR,          TR,          4       K  	  R #  L  \         d     R # i ; i L Le LF5i)Nr?   rI   )
rY  wait_until_readyRuntimeErrorr  rR  rq   r7   rl   rh  re  )r   r=   rh   s   &  r   r\  TimerCog._startup  s     	((++--- (()@AAAAyy{a
m+#--.CQtWMM//444  ((4!J-@ B . 		AM4sn   C;C# C!C# C;C5AC;C7C;C;2C93.C;!C# #C2.C;1C22C;7C;9C;c                  "   \        VP                  P                  4      pVP                  '       d   \        VP                  4      MR p\        P
                  ! \        WE\        VP                  4      W#4      G R j  xL
 w  rgV'       d)   VP                  P                  RR R R7      G R j  xL
  R # \        P                  P                  VR,          \        P                  4      p\        P                  P                  VR,          \        P                  4      p	\        P                  ! RRRV RVR	,           R
2R7      p
V
P                  RR\        P                   P#                  VR4       R\        P                   P#                  V	R4       R\        P                   P#                  V	R4       R2RR7       V
P%                  RR7       VP                  P                  RR R R7      G R j  xL
   VP&                  P)                  V
\+        VR,          4      \        P,                  P/                  4       R7      G R j  xL
 p\        P
                  ! \0        VR,          \        VP                  4      4      G R j  xL
  V P5                  VR,          VR,          4       R #  EL+ EL L Ll L0  \2         d     L;i ; i5i)Nu(   Couldn't arm that — try `/meta` again.r  r>   r?   u   🧨 Timer armedr   z<@z> is taking on **r5   z**.r   zDefuse windowu   🔓 opens r   u    · 💥 **detonates z** (Tu1   )
Hit 🧨 Defuse the moment you finish the task.Fr   zCMiss the window and the bomb detonates (rating loss). No reminders.)textu(   🧨 Armed — defuse it below, in time.rI   )r  r  allowed_mentions)r4  rS  rI   guild_idr  rR  rC   r:   r%  r'  r   r  r   r   r   r   r  r  
set_footerchannelro  r   AllowedMentionsnonerF   r  re  )r   r   r;   rG  r"   r9   rB   erropen_dtclose_dtr   rx  s   &&&&        r   rM  TimerCog.arm_timer  sa    +""%%&+6+?+?+?c+&&'T **+<cKLbLbHcelqq&&33<f:>T 4 K K K##11#i.(,,O$$223z?HLLQMM 2((*3%/@[AQ@RRU&VX	()@)@#)N(O P//6}}/F/FxQT/U.V W&}}66xEF GMN ! 	 	" 	
_`""//8bjnuy/zzz	#++00qz#d)?TBIBYBYB^B^B` 1 b bC##$4c$iSVVMMM 	  TC
O</ rK 	{bM 		s   A<K>J)?/K.J,/EK1J/2K7AJ5 J1=J5 J3J5 #K,K/K1J5 3J5 5K KKKc                  "   \         P                  ! \        V4      G R j  xL
 pV'       d   VR,          R8w  d(   VP                  P	                  RRR7      G R j  xL
  R # \        VP                  P                  4      VR,          8w  d(   VP                  P	                  RRR7      G R j  xL
  R # \        P                  ! 4       pWCR,          8  d   \        P                  P                  VR,          \        P                  4      pVP                  P	                  R	\        P                  P                  VR
4       R2RR7      G R j  xL
  R # \        WCR,          ,
          ^<,          ^4      p\         P                  ! \         W&R 4      G R j  xL
 pV'       g(   VP                  P	                  RRR7      G R j  xL
  R # V P#                  V4       V P%                  V4      G R j  xL
  \'        V \        VP                  P                  4      V4      pVP                  P	                  VP)                  R4      VRR7      G R j  xL
  VP+                  V4       R #  ELC EL EL EL L L L L)5i)NrQ   runningThis timer has ended.T	ephemeralrJ   z#You can only defuse your own timer.r>   u   Not yet — defusable r   .
started_tsThis timer has already ended.r   r  r  r  )r  rR  rt   r%  send_messager4  rS  rI   r7   r   r  r   r   r  r  r   ri   ra  rl  r   r  r  )	r   r   r   rU   r   r  rW   rh   r  s	   &&&      r   r   TimerCog.handle_defuse  s    ''AAg)3&&334KW[3\\\{""#uY'77&&334Yei3jjjiiky!!''55eI6FUG&&33()@)@#)N(OqQ]a 4 c c cc,$772=qA%%&:HTXYY&&334S_c3dddH%$$S)))c+*:*:*=*=&>D""//djj6JQUae/fff

;/ B\ k
c
 Zd 	*fs   I8I$I8.I8I'AI8.I*/BI8I-AI8I0I8! I8I2+I8-I4.AI8I6I8'I8*I8-I80I82I84I86I8c                t  "   \         P                  ! \        V4      G R j  xL
 pV'       d   VR,          R8w  d(   VP                  P	                  RRR7      G R j  xL
  R # \        VP                  P                  4      VR,          8w  d(   VP                  P	                  RRR7      G R j  xL
  R # \         P                  ! \        V4      G R j  xL
 pV'       g(   VP                  P	                  RRR7      G R j  xL
  R # V P                  V4       V P                  V4      G R j  xL
  \        P                  ! R	R
RVR,           R2R7      pVP                  R\        VR,          VR,          4      RR7       VP                  P	                  VRR7      G R j  xL
  R #  EL ELO L L L L L5i)NrQ   r  r  Tr  rJ   z$You can only abandon your own timer.r  rs  i r   r5   uQ   ** — conceded. Same cost as a detonation, but you owned it instead of ghosting.r   r   rO   rP   Fr   )r  r  )r  rR  rt   r%  r  r4  rS  rI   ro   ra  rl  r   r   r   ry   )r   r   r   rU   rh   r   s   &&&   r   r   TimerCog.handle_abandon  s}    ''AAg)3&&334KW[3\\\{""#uY'77&&334Zfj3kkk%%&:HEE&&334S_c3dddH%$$S)))MM 38)+C,<+= >O (PR 	
3u:s5z)JSXY""//a4/HHH# B\ lEd 	*
 	Is   F8F(F8.F8F+AF8.F./$F8F0F8  F8 F2+F8,F4-A4F8!F6"F8+F8.F80F82F84F86F8c                  "   \        VP                  P                  4      p\        P                  ! \
        V4      G R j  xL
 w  rE\        VP                  P                  V4      p\        W4      pV'       d(   VP                  P                  WgRR7      G R j  xL
  R # VP                  P                  WgRR7      G R j  xL
  R #  L L/ L
5i)NTr  )r4  rS  rI   r  rR  r.   r   rT  r-  r  ro  r%  r  )r   r   r  r"   r[   r5  r   r  s   &&&     r   r  TimerCog.open_meta  s     +""%%& **>3??[--::A>$&&++!$+OOO&&33!RV3WWW @ PWs6   >C CACC
&CCC
CCmetaz?Start something: pick a task, arm it, defuse it before it blows)r3   r   c                D   "   V P                  V4      G R j  xL
  R #  L5ir   )r  r   s   &&r   r  TimerCog.meta  s      nn[)))s     )rY  rZ  N)F)r   r   r   r   r   ra  re  rd  rh  rl  r\  rM  r   r   r  r   commandr  r   r   )r   s   @r   rW  rW  y  sg     @
U-
A=: 6I*X v&gi*i*r   rW  c                   "   V P                  \        \        4       V P                  \	        V 4      4      G Rj  xL
  R#  L5i)z9Loaded by handler.py via bot.load_extension('timer_bot').N)add_dynamic_itemsr   r   add_cogrW  )rY  s   &r   setupr    s+     ,6
++hsm
$$$s   8AAA)NNrt  )8r+  osr7   r   r  r   r   r   discord.extr   glicko2r   environrm  r   r   r   r    rS   rT   r   r   r   floatr
   r   r   r$   r*   r.   rC   rF   re   ri   rl   ro   rq   r-   rt   ry   r   r   r   r   DynamicItemr   r   r   r   r   r   r-  r?  CogrW  r  r|   r   r   <module>r     s   , + +       ::>>*&?@!5$ 
GS# ("**..56

{D12	"**..d34	W.
2%RP"G
:A7::))'***;*;<G] ABGJJ**7::+<+<=H_ BJ`wzz J`\jwzz j$f7::?? f0`*x|| `*H%r   