Files
game/addons/game_base/models/chat.py
T

134 lines
5.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
import re
from odoo import api, models, fields
# 游戏助手的展示昵称(前后端共用,落库消息的作者名)
GUIDE_NAME = '游戏助手'
def _plain(text):
"""去掉 HTML 标签,用于把 rule.desc(Html) 当作纯文本兜底。"""
if not text:
return ''
return re.sub(r'<[^>]+>', '', text).strip()
class GameChatChannel(models.Model):
_name = 'game.chat.channel'
_description = '世界聊天频道'
_order = 'sequence, id'
name = fields.Char(string='频道名', required=True)
channel_type = fields.Selection([
('world', '世界频道'),
('guild', '公会'),
('pm', '私聊'),
('guide', 'AI向导'),
], string='类型', default='world', index=True)
sequence = fields.Integer(string='排序', default=10)
creator_id = fields.Many2one('res.users', string='创建者')
member_ids = fields.Many2many('res.users', string='成员')
message_ids = fields.One2many('game.chat.message', 'channel_id', string='消息')
message_count = fields.Integer(string='消息数量', compute='_compute_message_count')
@api.depends('message_ids')
def _compute_message_count(self):
for rec in self:
rec.message_count = len(rec.message_ids)
def action_view_messages(self):
"""从频道列表跳转查看该频道全部消息。"""
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': '频道消息',
'res_model': 'game.chat.message',
'view_mode': 'list,form',
'domain': [('channel_id', '=', self.id)],
'context': dict(self.env.context),
}
def generate_guide_reply(self, question):
"""内置游戏知识引擎(零外部依赖):按关键词检索 game.rule / game.rule.category 作答。
预留扩展点:若需接入真实 LLM,替换本方法实现、返回模型生成的文本即可,其余调用方不变。
"""
q = (question or '').strip()
if not q:
return '你好,我是游戏助手。你可以问我关于「属性」「等级」「货币」「制度」的问题~'
env = self.env
Rule = env['game.rule']
Cat = env['game.rule.category']
def rules_of(key):
c = Cat.search([('key', '=', key)], limit=1)
return Rule.search([('category_id', '=', c.id)], order='name') if c else []
def line(r):
return f'· {r.name}:{r.summary or _plain(r.desc)}'
# 问候
if re.search(r'(你好|您好|hi|hello|在吗|嗨|早上好|晚上好)', q, re.I):
return ('你好,我是游戏助手 🤖 随时为你解答宇森世界的玩法。\n'
'可以问我:属性怎么算?怎么升级?货币有什么用?有哪些制度?')
# 属性(关键词覆盖攻击/物攻/法攻/防御/暴击等;穿透/韧性已移除)
_attr_re = re.search(r'(属性|攻击|物攻|法攻|防御|物防|法防|血量|生命|法力|速度|攻速|暴击|爆伤|命中|闪避|格挡|抗性|吸血|幸运)', q)
if _attr_re:
rules = list(rules_of('attribute_basic')) + list(rules_of('attribute_advanced'))
if rules:
head = '【属性规则】不同属性决定你的战斗表现,核心属性如下:'
return head + '\n' + '\n'.join(line(r) for r in rules[:12]) + '\n\n想深入了解某项,直接问我它的名字~'
# 等级
if re.search(r'(等级|升级|经验|世界等级|角色等级|怎么变强|变强)', q):
for key in ('world', 'character'):
rules = rules_of(key)
if rules:
c = Cat.search([('key', '=', key)], limit=1)
head = f'【{c.name}】'
lines = [f'· {r.name}(Lv{r.level}):{r.summary or ""}' for r in rules[:6]]
return head + '\n' + '\n'.join(l for l in lines if l.strip())
# 货币
if re.search(r'(货币|金币|钱|元宝|钻石|充值|兑换|经济)', q):
rules = rules_of('currency')
if rules:
head = '【货币规则】游戏内货币与获取/消耗方式:'
return head + '\n' + '\n'.join(line(r) for r in rules[:8])
# 制度 / 规则
if re.search(r'(制度|规定|规则|条款|公约|不能|禁止|惩罚|封号)', q):
rules = rules_of('system')
if rules:
head = '【制度说明】请遵守以下基本规则:'
return head + '\n' + '\n'.join(line(r) for r in rules[:8])
# 兜底:给出可问的方向
cats = Cat.search(
[('key', 'in', ['world', 'character', 'currency', 'attribute', 'system'])],
order='sequence')
tips = '、'.join(c.name for c in cats) if cats else '属性、等级、货币、制度'
return ('我是游戏助手,这个问题我还在学习中 🤔\n'
f'你可以问我这些方向:{tips}。\n例如:「攻击和物防怎么算?」「怎么升级最快?」')
class GameChatMessage(models.Model):
_name = 'game.chat.message'
_description = '聊天消息'
_order = 'id desc'
channel_id = fields.Many2one('game.chat.channel', string='频道',
ondelete='cascade', required=True, index=True)
author_id = fields.Many2one('res.users', string='发送者')
author_name = fields.Char(string='昵称')
body = fields.Text(string='内容', required=True)
@api.model_create_multi
def create(self, vals_list):
"""创建消息时自动过滤敏感词。"""
sanitize = self.env['game.sensitive.word'].sanitize
for vals in vals_list:
if vals.get('body'):
vals['body'] = sanitize(vals['body'])
return super(GameChatMessage, self).create(vals_list)