|  | @@ -23,15 +23,16 @@ class Main: | 
														
													
														
															
																|  |  | @classmethod |  |  | @classmethod | 
														
													
														
															
																|  |  | def main (cls, argv: list, argc: int) -> None: |  |  | def main (cls, argv: list, argc: int) -> None: | 
														
													
														
															
																|  |  | mode = Mode.NIZIKA |  |  | mode = Mode.NIZIKA | 
														
													
														
															
																|  |  | match (argc > 0) and argv[0]: |  |  |  | 
														
													
														
															
																|  |  |  |  |  | match (argc > 1) and argv[1]: | 
														
													
														
															
																|  |  | case '-g': |  |  | case '-g': | 
														
													
														
															
																|  |  | mode = Mode.GOATOH |  |  | mode = Mode.GOATOH | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | case '-w': |  |  | case '-w': | 
														
													
														
															
																|  |  | mode = Mode.DOUBLE |  |  | mode = Mode.DOUBLE | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | goatoh_mode = mode == Mode.GOATOH |  |  |  | 
														
													
														
															
																|  |  | double_mode = mode == Mode.DOUBLE |  |  |  | 
														
													
														
															
																|  |  |  |  |  | nizika_mode: bool = mode == Mode.NIZIKA | 
														
													
														
															
																|  |  |  |  |  | goatoh_mode: bool = mode == Mode.GOATOH | 
														
													
														
															
																|  |  |  |  |  | double_mode: bool = mode == Mode.DOUBLE | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | print (mode) |  |  | print (mode) | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
												
													
														
															
																|  | @@ -103,82 +104,112 @@ class Main: | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | message: str = chat_item.message |  |  | message: str = chat_item.message | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | # ChatGPT API を呼出し,返答を取得 |  |  |  | 
														
													
														
															
																|  |  | answer: str = Talk.main (message, chat_item.author['name'], histories, goatoh_mode).replace ('\n', ' ') |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | # 履歴に追加 |  |  |  | 
														
													
														
															
																|  |  | histories = (histories |  |  |  | 
														
													
														
															
																|  |  | + [{'role': 'user',      'content': message}, |  |  |  | 
														
													
														
															
																|  |  | {'role': 'assistant', 'content': answer}])[(-6):] |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | # ログ書込み |  |  |  | 
														
													
														
															
																|  |  | with open ('log.txt', 'a') as f: |  |  |  | 
														
													
														
															
																|  |  | f.write (f'{datetime.now ()}\t{json.dumps (chat_item.__dict__)}\t{answer}\n') |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | # 吹出し描画(ニジカは上,ゴートうは下) |  |  |  | 
														
													
														
															
																|  |  | screen.blit (balloon, (0, 384) if goatoh_mode else (0, 0)) |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | # 視聴者コメント描画 |  |  |  | 
														
													
														
															
																|  |  | screen.blit ( |  |  |  | 
														
													
														
															
																|  |  | user_font.render ( |  |  |  | 
														
													
														
															
																|  |  | '> ' + (message |  |  |  | 
														
													
														
															
																|  |  | if (CommonModule.len_by_full (message) |  |  |  | 
														
													
														
															
																|  |  | <= 21) |  |  |  | 
														
													
														
															
																|  |  | else (CommonModule.mid_by_full ( |  |  |  | 
														
													
														
															
																|  |  | message, 0, 19.5) |  |  |  | 
														
													
														
															
																|  |  | + '...')), |  |  |  | 
														
													
														
															
																|  |  | True, |  |  |  | 
														
													
														
															
																|  |  | (0, 0, 0)), |  |  |  | 
														
													
														
															
																|  |  | (120, 70 + 384) if goatoh_mode else (120, 70)) |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | # ニジカの返答描画 |  |  |  | 
														
													
														
															
																|  |  | screen.blit ( |  |  |  | 
														
													
														
															
																|  |  | nizika_font.render ( |  |  |  | 
														
													
														
															
																|  |  | (answer |  |  |  | 
														
													
														
															
																|  |  | if CommonModule.len_by_full (answer) <= 16 |  |  |  | 
														
													
														
															
																|  |  | else CommonModule.mid_by_full (answer, 0, 16)), |  |  |  | 
														
													
														
															
																|  |  | True, |  |  |  | 
														
													
														
															
																|  |  | (192, 0, 0)), |  |  |  | 
														
													
														
															
																|  |  | (100, 150 + 384) if goatoh_mode else (100, 150)) |  |  |  | 
														
													
														
															
																|  |  | if CommonModule.len_by_full (answer) > 16: |  |  |  | 
														
													
														
															
																|  |  |  |  |  | if nizika_mode: | 
														
													
														
															
																|  |  |  |  |  | goatoh_talking = False | 
														
													
														
															
																|  |  |  |  |  | if goatoh_mode: | 
														
													
														
															
																|  |  |  |  |  | goatoh_talking = True | 
														
													
														
															
																|  |  |  |  |  | if double_mode: | 
														
													
														
															
																|  |  |  |  |  | goatoh_talking: bool = random.random () < .5 | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | while True: | 
														
													
														
															
																|  |  |  |  |  | # ChatGPT API を呼出し,返答を取得 | 
														
													
														
															
																|  |  |  |  |  | answer: str = Talk.main (message, chat_item.author['name'], histories, goatoh_talking).replace ('\n', ' ') | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | # 履歴に追加 | 
														
													
														
															
																|  |  |  |  |  | histories = (histories | 
														
													
														
															
																|  |  |  |  |  | + [{'role': 'user',      'content': message}, | 
														
													
														
															
																|  |  |  |  |  | {'role': 'assistant', 'content': answer}])[(-12):] | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | # ログ書込み | 
														
													
														
															
																|  |  |  |  |  | with open ('log.txt', 'a') as f: | 
														
													
														
															
																|  |  |  |  |  | f.write (f'{datetime.now ()}\t{json.dumps (chat_item.__dict__)}\t{answer}\n') | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | # 吹出し描画(ニジカは上,ゴートうは下) | 
														
													
														
															
																|  |  |  |  |  | if nizika_mode: | 
														
													
														
															
																|  |  |  |  |  | screen.blit (balloon, (0, 0)) | 
														
													
														
															
																|  |  |  |  |  | if goatoh_mode: | 
														
													
														
															
																|  |  |  |  |  | screen.blit (balloon, (0, 384)) | 
														
													
														
															
																|  |  |  |  |  | if double_mode: | 
														
													
														
															
																|  |  |  |  |  | screen.blit (pygame.transform.flip ( | 
														
													
														
															
																|  |  |  |  |  | balloon, | 
														
													
														
															
																|  |  |  |  |  | not goatoh_talking, | 
														
													
														
															
																|  |  |  |  |  | False), | 
														
													
														
															
																|  |  |  |  |  | (0, 0)) | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | # 視聴者コメント描画 | 
														
													
														
															
																|  |  |  |  |  | screen.blit ( | 
														
													
														
															
																|  |  |  |  |  | user_font.render ( | 
														
													
														
															
																|  |  |  |  |  | '> ' + (message | 
														
													
														
															
																|  |  |  |  |  | if (CommonModule.len_by_full (message) | 
														
													
														
															
																|  |  |  |  |  | <= 21) | 
														
													
														
															
																|  |  |  |  |  | else (CommonModule.mid_by_full ( | 
														
													
														
															
																|  |  |  |  |  | message, 0, 19.5) | 
														
													
														
															
																|  |  |  |  |  | + '...')), | 
														
													
														
															
																|  |  |  |  |  | True, | 
														
													
														
															
																|  |  |  |  |  | (0, 0, 0)), | 
														
													
														
															
																|  |  |  |  |  | (120, 70 + 384) if goatoh_mode else (120 + (64 if (double_mode and not goatoh_talking) else 0), 70)) | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | # ニジカの返答描画 | 
														
													
														
															
																|  |  | screen.blit ( |  |  | screen.blit ( | 
														
													
														
															
																|  |  | nizika_font.render ( |  |  | nizika_font.render ( | 
														
													
														
															
																|  |  | (CommonModule.mid_by_full (answer, 16, 16) |  |  |  | 
														
													
														
															
																|  |  | if CommonModule.len_by_full (answer) <= 32 |  |  |  | 
														
													
														
															
																|  |  | else (CommonModule.mid_by_full ( |  |  |  | 
														
													
														
															
																|  |  | answer, 16, 14.5) |  |  |  | 
														
													
														
															
																|  |  | + '...')), |  |  |  | 
														
													
														
															
																|  |  | True, |  |  |  | 
														
													
														
															
																|  |  | (192, 0, 0)), |  |  |  | 
														
													
														
															
																|  |  | (100, 200 + 384) if goatoh_mode else (100, 200)) |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | pygame.display.update () |  |  |  | 
														
													
														
															
																|  |  | 
 |  |  |  | 
														
													
														
															
																|  |  | # 鳴く. |  |  |  | 
														
													
														
															
																|  |  | if goatoh_mode: |  |  |  | 
														
													
														
															
																|  |  | if random.random () < 0.1: |  |  |  | 
														
													
														
															
																|  |  | kusa.play () |  |  |  | 
														
													
														
															
																|  |  |  |  |  | (answer | 
														
													
														
															
																|  |  |  |  |  | if CommonModule.len_by_full (answer) <= 16 | 
														
													
														
															
																|  |  |  |  |  | else CommonModule.mid_by_full (answer, 0, 16)), | 
														
													
														
															
																|  |  |  |  |  | True, | 
														
													
														
															
																|  |  |  |  |  | (192, 0, 0)), | 
														
													
														
															
																|  |  |  |  |  | (100, 150 + 384) if goatoh_mode else (100 + (64 if (double_mode and not goatoh_talking) else 0), 150)) | 
														
													
														
															
																|  |  |  |  |  | if CommonModule.len_by_full (answer) > 16: | 
														
													
														
															
																|  |  |  |  |  | screen.blit ( | 
														
													
														
															
																|  |  |  |  |  | nizika_font.render ( | 
														
													
														
															
																|  |  |  |  |  | (CommonModule.mid_by_full (answer, 16, 16) | 
														
													
														
															
																|  |  |  |  |  | if CommonModule.len_by_full (answer) <= 32 | 
														
													
														
															
																|  |  |  |  |  | else (CommonModule.mid_by_full ( | 
														
													
														
															
																|  |  |  |  |  | answer, 16, 14.5) | 
														
													
														
															
																|  |  |  |  |  | + '...')), | 
														
													
														
															
																|  |  |  |  |  | True, | 
														
													
														
															
																|  |  |  |  |  | (192, 0, 0)), | 
														
													
														
															
																|  |  |  |  |  | (100, 200 + 384) if goatoh_mode else (100 + (64 if (double_mode and not goatoh_talking) else 0), 200)) | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | pygame.display.update () | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | # 鳴く. | 
														
													
														
															
																|  |  |  |  |  | if goatoh_talking: | 
														
													
														
															
																|  |  |  |  |  | if random.random () < .1: | 
														
													
														
															
																|  |  |  |  |  | kusa.play () | 
														
													
														
															
																|  |  |  |  |  | else: | 
														
													
														
															
																|  |  |  |  |  | mumumumu.play () | 
														
													
														
															
																|  |  | else: |  |  | else: | 
														
													
														
															
																|  |  | mumumumu.play () |  |  |  | 
														
													
														
															
																|  |  | else: |  |  |  | 
														
													
														
															
																|  |  | noon.play () |  |  |  | 
														
													
														
															
																|  |  |  |  |  | noon.play () | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | time.sleep (1.5) | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | # 返答の読上げを WAV ディタとして生成,取得 | 
														
													
														
															
																|  |  |  |  |  | try: | 
														
													
														
															
																|  |  |  |  |  | wav: bytearray | None = Aques.main (answer, goatoh_talking) | 
														
													
														
															
																|  |  |  |  |  | except: | 
														
													
														
															
																|  |  |  |  |  | wav: None = None | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | # 読上げを再生 | 
														
													
														
															
																|  |  |  |  |  | if wav is not None: | 
														
													
														
															
																|  |  |  |  |  | with open ('./nizika_talking.wav', 'wb') as f: | 
														
													
														
															
																|  |  |  |  |  | f.write (wav) | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | playsound ('./nizika_talking.wav') | 
														
													
														
															
																|  |  |  |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | time.sleep (10) | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | time.sleep (1.5) |  |  |  | 
														
													
														
															
																|  |  |  |  |  | if not double_mode or random.random () < .5: | 
														
													
														
															
																|  |  |  |  |  | break | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | # 返答の読上げを WAV ディタとして生成,取得 |  |  |  | 
														
													
														
															
																|  |  | try: |  |  |  | 
														
													
														
															
																|  |  | wav: bytearray | None = Aques.main (answer, goatoh_mode) |  |  |  | 
														
													
														
															
																|  |  | except: |  |  |  | 
														
													
														
															
																|  |  | wav: None = None |  |  |  | 
														
													
														
															
																|  |  |  |  |  | screen.fill ((0, 255, 0)) | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | # 再生 |  |  |  | 
														
													
														
															
																|  |  | if wav is not None: |  |  |  | 
														
													
														
															
																|  |  | with open ('./nizika_talking.wav', 'wb') as f: |  |  |  | 
														
													
														
															
																|  |  | f.write (wav) |  |  |  | 
														
													
														
															
																|  |  |  |  |  | chat_item.author['name'] = 'ゴートうひとり' if goatoh_talking else '伊地知ニジカ' | 
														
													
														
															
																|  |  |  |  |  | chat_item.author['id'] = '' | 
														
													
														
															
																|  |  |  |  |  | chat_item.author['channelId'] = './favicon-goatoh.ico' if goatoh_talking else './favicon.ico' | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | playsound ('./nizika_talking.wav') |  |  |  | 
														
													
														
															
																|  |  |  |  |  | goatoh_talking = not goatoh_talking | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | time.sleep (10) |  |  |  | 
														
													
														
															
																|  |  |  |  |  | message = histories.pop (-1)['content'] | 
														
													
														
															
																|  |  | else: |  |  | else: | 
														
													
														
															
																|  |  | # Chat オブジェクトが無効 |  |  | # Chat オブジェクトが無効 | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
												
													
														
															
																|  | 
 |