
    [6j                       d Z ddlmZ ddlZddlZddlZddlZddlmZm	Z	 ddl
mZ ddlmZmZ ddlmZ ddlmZmZ  ed	          Z ee                                          j        d
         Zej                            dd          Z ee          Z G d de          ZddZddZddZ e!dk    r e              dS dS )u  狼人杀 live 服务(多人房间版):密钥建房 → 邀请码加入 → 多真人 + AI 补位,每房一局隔离。

  PYTHONPATH=src python -m genesis.server.werewolf_server            # 真 AI(MiniMax)
  GENESIS_WW_BRAIN=random PYTHONPATH=src python -m genesis.server.werewolf_server   # 随机 bot,免费快测

身份:create/join 返回 token(浏览器存 localStorage),后续请求带 token → 定位房间+座位。
房间接口:/api/room/{create,join,start,leave,close,continue};对局接口按 token:/api/{state,action,spoken,voice}。
语音:/api/tts(text+seat→mp3,法官 seat=0)、/api/asr(16k PCM→文本)、ws://host:port+1 流式 ASR。静态走 repo 根。
    )annotationsN)SimpleHTTPRequestHandlerThreadingHTTPServer)Path)parse_qsurlparse)
get_logger)RoomManagertts_mp3zserver.werewolf   GENESIS_WW_BRAINllm)brainc                  N     e Zd Z fdZdddZdd	ZddZ fdZd Zd Z	 xZ
S )Handlerc                b     t                      j        |dt          t                    i| d S )N	directory)super__init__strROOT)selfakw	__class__s      9/root/genesis-world/src/genesis/server/werewolf_server.pyr   zHandler.__init__   s0    !7s4yy7B77777       codeintreturnNonec                   t          j        |d                              d          }|                     |           |                     dd           |                     dt          t          |                               |                     dd           |                                  | j        	                    |           d S )	NF)ensure_asciizutf-8Content-Typezapplication/json; charset=utf-8Content-LengthCache-Controlno-store)
jsondumpsencodesend_responsesend_headerr   lenend_headerswfilewrite)r   objr   bs       r   _jsonzHandler._json#   s    Js///66w??4   )JKKK)3s1vv;;777*555
r   dictc                    t          | j                            dd                    }	 t          j        |r| j                            |          nd          S # t          $ r i cY S w xY w)Nr&   r   s   {})r    headersgetr)   loadsrfileread	Exception)r   ns     r   _bodyzHandler._body,   ss      !115566	:A@djooa0005AAA 	 	 	III	s   /A A)(A)mp3bytesc                D   |                      d           |                     dd           |                     dt          t          |                               |                     dd           |                                  | j                            |           d S )Nr   r%   z
audio/mpegr&   r'   r(   )r,   r-   r   r.   r/   r0   r1   )r   r?   s     r   _audiozHandler._audio3   s    3666)3s3xx==999*555
r   c                z   t          | j                  }|j        dk    rzt          |j                                      d          pdgd         }t
                              |          }|                     |r|                    |          nddi           d S t                      
                                 d S )Nz
/api/statetoken r   phasenone)r   pathr   queryr8   _MGRroom_ofr4   	state_forr   do_GET)r   urD   roomr   s       r   rM   zHandler.do_GET<   s    TY6\!!ag&&**733;tQ?E<<&&DJJKt~~e,,,7F:KLLLFr   c                b   t          | j                  j        }|dk    r|                                 ni }|                    dd          }|dk    rct                              |                    dd          |                    dd                    }|                     |pddi|rd	nd
           d S |dk    rX|                     t                              |                    dd          |                    dd                               d S t                              |          }|dv r:|s|                     dddd           d S |dk    r,|                     d|	                    |          i           n|dk    r.|
                    |           |                     ddi           n|dk    rA|                     d|                    ||                    dd                    i           nn|dk    r,|                     d|                    |          i           n<|dk    rL|                     d|                    |t          |                    d                              i           n|dk    r@|                     d|                    ||                    dd                    i           n|dk    rT|                    |                    d          |                    d                     |                     ddi           nJ|d k    rDt          |                    d!                    |_        |                     d|j        d"           d S |d#k    r|                    d          pd                                d d$         }t'          |                    dd%                    }|s|                     ddid$           d S d%d&lm} 	 |                     t/          | ||                               nu# t0          $ rh}	t2                              d't7          |	          d d(                    |                     dt7          |	          d d	         dd)           Y d }	~	nd }	~	ww xY wd S |dk    rt'          | j                            d*d%                    }
|
r| j                            |
          nd+}|s|                     dd,dd$           d S d%d-lm } 	 |                     d ||d./          d0           nu# t0          $ rh}	t2                              d1t7          |	          d d(                    |                     dt7          |	          d d	         dd)           Y d }	~	nd }	~	ww xY wd S | !                    d           d S )2Nz/api/asrrD   rE   z/api/room/createkeynicknameerroru   密钥错误,无权创建房间r   i  z/api/room/joinr   )/api/room/start/api/room/leave/api/room/close/api/room/kick/api/room/continue/api/action/api/spoken
/api/voiceFu    房间不存在(可能已解散))okrS   i  rT   r\   rU   TrW   pidrV   rX   contrY   answerrZ   seattextr[   on)r\   voicez/api/ttsi  r   )voice_for_seatu   TTS 失败:%s   i  r&   r   empty)	recognizei>  )rate)r\   ra   u   ASR 失败:%s)"r   rH   r>   r8   rJ   creater4   joinrK   
start_gameleavekickclosecontinue_gameboolsubmitmark_spokenvoice_onstripr    genesis.voice.volc_ttsrd   rB   r   r<   loggerwarningr   r7   r:   r;   genesis.voice.volc_asrrg   
send_error)r   pr3   rD   outrO   ra   r`   rd   er=   pcmrg   s                r   do_POSTzHandler.do_POSTF   s   TY$OODJJLLLgr"""""++aeeE2..j"0E0EFFCJJsJw(IJSVL_CC\_```F   JJtyyvr!2!2AEE*b4I4IJJKKKF||E"" S S S d

%2TUUWZ[[[]c]c%%%

D$//%"8"89::::'''

5!!!4::tTl#;#;#;#;&&&

D$))E1553C3C"D"DEFFFF'''

D$**U"3"345555***

D$"4"4UDv<O<O"P"PQRRRRm##

D$++eQUU8R5H5H"I"IJKKKKm##  vf>>>

DRV<@X@X@X@Xl"" $QUU4[[ 1 14::TTXTa>b>b3c3c3cF
??EE&MM'R..00#6DquuVQ''((D 7

D%=#...======uGD..*>*>??@@@@ u u uAtt===tzzQVadefagaghlilhlamJnJnps?t?t?t?t?t?t?t?tuF
??DL$$%5q99::A()2$*//!$$$sC I

%'::C@@@&&888888u

$		#E0J0J0JKKLLLL u u uAtt===tzzQVadefagaghlilhlamJnJnps?t?t?t?t?t?t?t?tuFs2   *,P 
R	!ARR	?#T# #
V-AVVc                    d S )N )r   r   s     r   log_messagezHandler.log_message   s    r   )r   )r   r    r!   r"   )r!   r5   )r?   r@   r!   r"   )__name__
__module____qualname__r   r4   r>   rB   rM   r~   r   __classcell__)r   s   @r   r   r      s        8 8 8 8 8              : : :x      r   r   hostr   portr    r!   r"   c                    ddl 	 ddln3# t          $ r&}t                              d|           Y d}~dS d}~ww xY wddlm fd fd}                                }                    |           	 |	                     |                       dS # t          $ r<}t                              dt          |          dd                    Y d}~dS d}~ww xY w)	u   流式 ASR 的 WebSocket 服务(浏览器边说边送 PCM,火山中间识别结果实时回传)。独立端口,守护线程 asyncio。r   Nu)   未装 websockets,流式 ASR 不可用:%s)relayc                   K   	  |            d {V  d S # t           $ r;}t                              dt          |          d d                    Y d }~d S d }~ww xY w)Nu   ASR WS 桥异常:%sre   )r<   rv   rw   r   )wsargsr|   r   s      r   handlerz_start_asr_ws.<locals>.handler   s      	@%))OOOOOOOOO 	@ 	@ 	@NN0#a&&#,?????????	@s    
A0AAc                    K                        d           4 d {V                                    d {V  d d d           d {V  d S # 1 d {V swxY w Y   d S )N)max_size)serveFuture)asyncior   r   r   
websocketss   r   r   z_start_asr_ws.<locals>.serve   s     ##GT4$#GG 	# 	# 	# 	# 	# 	# 	# 	#.."""""""""	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	# 	#s   A
AAu$   ASR WS 服务起不来(端口 %d):%sre   )r   r   r<   rv   rw   rx   r   new_event_loopset_event_looprun_until_completer   )	r   r   r|   r   loopr   r   r   r   s	   ``   @@@@r   _start_asr_wsr      sn   NNNO O O OBAFFFO,,,,,,@ @ @ @ @# # # # # # # # # !!##D4   S((((( S S S=tSVVDSD\RRRRRRRRRSs*    
A<AB! !
C'+1C""C'c                     ddl } 	 	 t                                           n*# t          $ r t                              d           Y nw xY w|                     d           [)uW   周期清理:CLOSED / 闲置(空房 5min,否则 1h)房间销毁 + 掉线补位检查。r   NTu   房间清理异常   )timerJ   cleanupr<   rv   	exceptionsleep)r   s    r   _cleanup_loopr      sn    KKK	3LLNNNN 	3 	3 	3122222	3

2s   ! $AAc            
     *   t          j                    } |                     dt          j                            dd                     |                     dt          t          t          j                            dd                               |                                 }|j        d	z   }t          j
        t          |j        |fd
d                                           t          j
        t          d
d                                           t                              d|j        |j        t"                     t                              d|j        |           t%          |j        |j        ft&                                                     d S )Nz--hostGENESIS_WW_HOSTz	127.0.0.1)defaultz--portGENESIS_WW_PORT8132)typer      Tzasr-ws)targetr   daemonnamezroom-cleanup)r   r   r   uW   🐺 狼人杀(多人房)live:http://%s:%d/src/genesis/viz/web/werewolf.html (brain=%s)u   🎤 流式 ASR WS:ws://%s:%d)argparseArgumentParseradd_argumentosenvironr8   r    
parse_argsr   	threadingThreadr   r   startr   rv   info_BRAINr   r   serve_forever)apr   asr_ports      r   mainr      s;   		 	"	"BOOHbjnn5F&T&TOUUUOOH3BJNNCTV\4]4]0^0^O___==??Dy1}HMH0EdYabbbhhjjjM$^LLLRRTTT
KKi	49f. . .
KK/HEEEDI.88FFHHHHHr   __main__)r   r   r   r    r!   r"   )r!   r"   )"__doc__
__future__r   r   r)   r   r   http.serverr   r   pathlibr   urllib.parser   r   genesis.obs.logging_setupr	   genesis.werewolf.roomsr
   r   rv   __file__resolveparentsr   r   r8   r   rJ   r   r   r   r   r   r   r   r   <module>r      s    # " " " " "   				     E E E E E E E E       + + + + + + + + 0 0 0 0 0 0 7 7 7 7 7 7 7 7	%	&	&tH~~'*	*E	2	2{   e e e e e& e e ePS S S S6   I I I I zDFFFFF r   