107 lines
4.9KB

  1. # encoding:utf-8
  2. import plugins
  3. from bridge.bridge import Bridge
  4. from bridge.context import ContextType
  5. from bridge.reply import Reply, ReplyType
  6. from common import const
  7. from common.expired_dict import ExpiredDict
  8. from common.log import logger
  9. from config import conf
  10. from plugins import *
  11. # https://github.com/bupticybee/ChineseAiDungeonChatGPT
  12. class StoryTeller:
  13. def __init__(self, bot, sessionid, story):
  14. self.bot = bot
  15. self.sessionid = sessionid
  16. bot.sessions.clear_session(sessionid)
  17. self.first_interact = True
  18. self.story = story
  19. def reset(self):
  20. self.bot.sessions.clear_session(self.sessionid)
  21. self.first_interact = True
  22. def action(self, user_action):
  23. if user_action[-1] != "。":
  24. user_action = user_action + "。"
  25. if self.first_interact:
  26. prompt = (
  27. """现在来充当一个文字冒险游戏,描述时候注意节奏,不要太快,仔细描述各个人物的心情和周边环境。一次只需写四到六句话。
  28. 开头是,"""
  29. + self.story
  30. + " "
  31. + user_action
  32. )
  33. self.first_interact = False
  34. else:
  35. prompt = """继续,一次只需要续写四到六句话,总共就只讲5分钟内发生的事情。""" + user_action
  36. return prompt
  37. @plugins.register(
  38. name="Dungeon",
  39. desire_priority=0,
  40. namecn="文字冒险",
  41. desc="A plugin to play dungeon game",
  42. version="1.0",
  43. author="lanvent",
  44. )
  45. class Dungeon(Plugin):
  46. def __init__(self):
  47. super().__init__()
  48. self.handlers[Event.ON_HANDLE_CONTEXT] = self.on_handle_context
  49. logger.info("[Dungeon] inited")
  50. # 目前没有设计session过期事件,这里先暂时使用过期字典
  51. if conf().get("expires_in_seconds"):
  52. self.games = ExpiredDict(conf().get("expires_in_seconds"))
  53. else:
  54. self.games = dict()
  55. def on_handle_context(self, e_context: EventContext):
  56. if e_context["context"].type != ContextType.TEXT:
  57. return
  58. bottype = Bridge().get_bot_type("chat")
  59. if bottype not in [const.OPEN_AI, const.CHATGPT, const.CHATGPTONAZURE, const.LINKAI]:
  60. return
  61. bot = Bridge().get_bot("chat")
  62. content = e_context["context"].content[:]
  63. clist = e_context["context"].content.split(maxsplit=1)
  64. sessionid = e_context["context"]["session_id"]
  65. logger.debug("[Dungeon] on_handle_context. content: %s" % clist)
  66. trigger_prefix = conf().get("plugin_trigger_prefix", "$")
  67. if clist[0] == f"{trigger_prefix}停止冒险":
  68. if sessionid in self.games:
  69. self.games[sessionid].reset()
  70. del self.games[sessionid]
  71. reply = Reply(ReplyType.INFO, "冒险结束!")
  72. e_context["reply"] = reply
  73. e_context.action = EventAction.BREAK_PASS
  74. elif clist[0] == f"{trigger_prefix}开始冒险" or sessionid in self.games:
  75. if sessionid not in self.games or clist[0] == f"{trigger_prefix}开始冒险":
  76. if len(clist) > 1:
  77. story = clist[1]
  78. else:
  79. story = "你在树林里冒险,指不定会从哪里蹦出来一些奇怪的东西,你握紧手上的手枪,希望这次冒险能够找到一些值钱的东西,你往树林深处走去。"
  80. self.games[sessionid] = StoryTeller(bot, sessionid, story)
  81. reply = Reply(ReplyType.INFO, "冒险开始,你可以输入任意内容,让故事继续下去。故事背景是:" + story)
  82. e_context["reply"] = reply
  83. e_context.action = EventAction.BREAK_PASS # 事件结束,并跳过处理context的默认逻辑
  84. else:
  85. prompt = self.games[sessionid].action(content)
  86. e_context["context"].type = ContextType.TEXT
  87. e_context["context"].content = prompt
  88. e_context.action = EventAction.BREAK # 事件结束,不跳过处理context的默认逻辑
  89. def get_help_text(self, **kwargs):
  90. help_text = "可以和机器人一起玩文字冒险游戏。\n"
  91. if kwargs.get("verbose") != True:
  92. return help_text
  93. trigger_prefix = conf().get("plugin_trigger_prefix", "$")
  94. help_text = f"{trigger_prefix}开始冒险 " + "背景故事: 开始一个基于{背景故事}的文字冒险,之后你的所有消息会协助完善这个故事。\n" + f"{trigger_prefix}停止冒险: 结束游戏。\n"
  95. if kwargs.get("verbose") == True:
  96. help_text += f"\n命令例子: '{trigger_prefix}开始冒险 你在树林里冒险,指不定会从哪里蹦出来一些奇怪的东西,你握紧手上的手枪,希望这次冒险能够找到一些值钱的东西,你往树林深处走去。'"
  97. return help_text