import { extension_settings, getContext } from "../../../../extensions.js"; import { saveSettingsDebounced } from "../../../../../script.js"; import { EXT_ID } from "../core/constants.js"; import { createModuleEvents, event_types } from "../core/event-manager.js"; const MODULE_NAME = "wallhavenBackground"; const messageEvents = createModuleEvents('wallhaven:messages'); const globalEvents = createModuleEvents('wallhaven'); const defaultSettings = { enabled: false, bgMode: false, category: "010", purity: "100", opacity: 0.3, customTags: [] }; const tagWeights = { custom: 3.0, characters: 3, locations: 3, nsfw_actions: 3, intimate_settings: 3, poses: 2, clothing: 2, nsfw_body_parts: 2, activities: 2, expressions: 1.5, body_features: 1.5, nsfw_states: 1.5, fetish_categories: 1.5, clothing_states: 1.5, nsfw_descriptions: 1.5, colors: 1, objects: 1, weather_time: 1, styles: 1, emotional_states: 1, romance_keywords: 1, body_modifications: 1, nsfw_sounds: 1 }; const wallhavenTags = { characters: { // 基础人称 "女孩": "anime girl", "少女": "anime girl", "女性": "woman", "女人": "woman", "男孩": "boy", "少年": "boy", "男性": "man", "男人": "man", "美女": "beautiful woman", "帅哥": "handsome man", "女生": "girl", "男生": "boy", // 职业角色 "女仆": "maid", "侍女": "maid", "佣人": "maid", "管家": "butler", "秘书": "secretary", "助理": "assistant", "下属": "subordinate", "老板": "boss", "上司": "superior", "领导": "leader", "经理": "manager", "同事": "colleague", "伙伴": "partner", "搭档": "partner", "客户": "client", "顾客": "customer", "委托人": "client", // 学校相关 "学生": "student", "学员": "student", "同学": "student", "男同学": "male student", "女同学": "schoolgirl", "女学生": "schoolgirl", "男学生": "male student", "老师": "teacher", "教师": "teacher", "先生": "teacher", "导师": "mentor", "校长": "principal", "教授": "professor", "讲师": "lecturer", "学姐": "senior student", "学妹": "junior student", "学长": "senior student", "学弟": "junior student", "班长": "class president", "社长": "club president", // 医疗相关 "护士": "nurse", "白衣天使": "nurse", "医护": "nurse", "医生": "doctor", "大夫": "doctor", "医师": "physician", "病人": "patient", "患者": "patient", // 家庭关系 "母亲": "mother", "妈妈": "mother", "母": "mother", "妈": "mother", "父亲": "father", "爸爸": "father", "父": "father", "爸": "father", "姐姐": "sister", "妹妹": "sister", "哥哥": "brother", "弟弟": "brother", "女儿": "daughter", "闺女": "daughter", "儿子": "son", "妻子": "wife", "老婆": "wife", "丈夫": "husband", "老公": "husband", "岳母": "mother-in-law", "婆婆": "mother-in-law", "丈母娘": "mother-in-law", "阿姨": "aunt", "叔叔": "uncle", "表姐": "cousin", "表妹": "cousin", "邻居": "neighbor", "房东": "landlord", "租客": "tenant", // 特殊身份 "公主": "princess", "殿下": "princess", "王女": "princess", "王子": "prince", "王子殿下": "prince", "皇子": "prince", "女王": "queen", "国王": "king", "皇帝": "emperor", "皇后": "empress", "贵族": "noble", "富家千金": "rich girl", "大小姐": "young lady", "平民": "commoner", "村民": "villager", "市民": "citizen", // 二次元角色 "猫娘": "catgirl", "猫女": "catgirl", "猫咪女孩": "catgirl", "狐娘": "fox girl", "狐狸女孩": "fox girl", "狐仙": "fox girl", "兔娘": "bunny girl", "兔女郎": "bunny girl", "兔子女孩": "bunny girl", "狼娘": "wolf girl", "犬娘": "dog girl", "龙娘": "dragon girl", "魔女": "witch", "女巫": "witch", "巫女": "witch", "魔法少女": "magical girl", "天使": "angel", "小天使": "angel", "堕天使": "fallen angel", "恶魔": "demon", "魅魔": "demon", "小恶魔": "demon", "精灵": "elf", "森林精灵": "elf", "暗精灵": "dark elf", "吸血鬼": "vampire", "血族": "vampire", "僵尸": "zombie", "人偶": "doll", "机器人": "android", "人造人": "artificial human", "外星人": "alien", "异世界人": "otherworld person", // 职业类型 "忍者": "ninja", "女忍": "ninja", "武士": "warrior", "剑士": "swordsman", "骑士": "knight", "圣骑士": "paladin", "战士": "warrior", "法师": "wizard", "魔法师": "wizard", "术士": "sorcerer", "牧师": "priest", "修女": "nun", "尼姑": "nun", "盗贼": "thief", "刺客": "assassin", "间谍": "spy", "雇佣兵": "mercenary", "佣兵": "mercenary", "赏金猎人": "bounty hunter", // 现代职业 "警察": "police", "警官": "police", "侦探": "detective", "探长": "detective", "消防员": "firefighter", "消防": "firefighter", "军人": "soldier", "士兵": "soldier", "特种兵": "special forces", "飞行员": "pilot", "船长": "captain", "司机": "driver", "厨师": "chef", "料理师": "chef", "服务员": "waitress", "调酒师": "bartender", "咖啡师": "barista", "艺术家": "artist", "画家": "artist", "雕塑家": "sculptor", "音乐家": "musician", "歌手": "singer", "偶像": "idol", "演员": "actress", "模特": "model", "舞者": "dancer", "作家": "writer", "记者": "journalist", "编辑": "editor", "科学家": "scientist", "研究员": "scientist", "博士": "doctor", "程序员": "programmer", "工程师": "engineer", "设计师": "designer", "商人": "businessman", "企业家": "entrepreneur", "投资者": "investor", // 特殊关系 "新娘": "bride", "新嫁娘": "bride", "新郎": "groom", "前女友": "ex-girlfriend", "前男友": "ex-boyfriend", "青梅竹马": "childhood friend", "闺蜜": "best friend", "好友": "friend", "对手": "rival", "敌人": "enemy", "仇人": "enemy", "陌生人": "stranger", "路人": "passerby", "访客": "visitor" }, clothing: { // 裙装类 "连衣裙": "dress", "裙子": "dress", "长裙": "long dress", "短裙": "short dress", "迷你裙": "mini dress", "中裙": "midi dress", "蓬蓬裙": "puffy dress", "紧身裙": "tight dress", "A字裙": "a-line dress", "包臀裙": "pencil skirt", "百褶裙": "pleated skirt", "伞裙": "circle skirt", "吊带裙": "slip dress", // 制服类 "校服": "school uniform", "制服": "uniform", "学生服": "school uniform", "女仆装": "maid outfit", "女仆服": "maid outfit", "护士服": "nurse outfit", "白大褂": "nurse outfit", "警服": "police uniform", "军装": "military uniform", "空姐服": "flight attendant uniform", "服务员服": "waitress uniform", "OL装": "office lady outfit", "职业装": "business attire", // 传统服装 "和服": "kimono", "浴衣": "kimono", "振袖": "kimono", "旗袍": "qipao", "中式服装": "chinese dress", "汉服": "hanfu", "洛丽塔": "lolita dress", "哥特装": "gothic dress", // 特殊场合 "婚纱": "wedding dress", "新娘装": "wedding dress", "礼服": "evening gown", "晚礼服": "evening dress", "舞会裙": "ball gown", "宴会服": "party dress", "演出服": "performance outfit", "舞台装": "stage outfit", // 休闲装 "T恤": "t-shirt", "衬衫": "shirt", "衬衣": "blouse", "吊带": "tank top", "背心": "vest", "卫衣": "hoodie", "夹克": "jacket", "外套": "coat", "风衣": "trench coat", "毛衣": "sweater", "针织衫": "knit sweater", "开衫": "cardigan", // 裤装 "牛仔裤": "jeans", "裤子": "pants", "短裤": "shorts", "热裤": "hot pants", "紧身裤": "leggings", "喇叭裤": "flare pants", "西装裤": "suit pants", "休闲裤": "casual pants", // 运动装 "运动服": "sportswear", "瑜伽服": "yoga outfit", "健身服": "gym wear", "田径服": "track suit", "篮球服": "basketball uniform", // 睡衣家居 "睡衣": "pajamas", "居家服": "pajamas", "睡袍": "nightgown", "浴袍": "bathrobe", "晨袍": "morning robe", "家居服": "loungewear", // 泳装 "泳装": "swimsuit", "泳衣": "swimsuit", "比基尼": "bikini", "连体泳衣": "one-piece swimsuit", "三点式": "bikini", // 内衣 "内衣": "lingerie", "胸罩": "bra", "内裤": "panties", "文胸": "bra", "胖次": "panties", "三角裤": "briefs", "平角裤": "boxers", "内衣套装": "lingerie set", "情趣内衣": "sexy lingerie", "蕾丝内衣": "lace lingerie", // 袜类 "丝袜": "stockings", "长筒袜": "stockings", "连裤袜": "pantyhose", "过膝袜": "thigh highs", "短袜": "ankle socks", "船袜": "no-show socks", "网袜": "fishnet stockings", "白丝": "white stockings", "黑丝": "black stockings", // 鞋类 "高跟鞋": "high heels", "靴子": "boots", "凉鞋": "sandals", "平底鞋": "flats", "帆布鞋": "canvas shoes", "运动鞋": "sneakers", "马丁靴": "combat boots", "长靴": "knee boots", "短靴": "ankle boots", "拖鞋": "slippers", "人字拖": "flip flops", // 配饰 "手套": "gloves", "帽子": "hat", "眼镜": "glasses", "太阳镜": "sunglasses", "发带": "headband", "头巾": "headscarf", "围巾": "scarf", "披肩": "shawl", "领带": "tie", "蝴蝶结": "bow tie", "腰带": "belt", "围裙": "apron", // 首饰 "项链": "necklace", "耳环": "earrings", "戒指": "ring", "手镯": "bracelet", "脚链": "anklet", "发饰": "hair accessory", "胸针": "brooch", "手表": "watch" }, body_features: { // 发型 "长发": "long hair", "短发": "short hair", "中发": "medium hair", "马尾": "ponytail", "双马尾": "twintails", "侧马尾": "side ponytail", "丸子头": "bun", "包子头": "bun", "公主头": "half updo", "刘海": "bangs", "齐刘海": "straight bangs", "斜刘海": "side bangs", "卷发": "curly hair", "直发": "straight hair", "波浪发": "wavy hair", "盘发": "updo", "编发": "braided hair", "麻花辫": "braids", "单边辫": "side braid", "双辫": "twin braids", "蓬松发": "voluminous hair", "顺滑发": "silky hair", // 发色 "黑发": "black hair", "金发": "blonde hair", "棕发": "brown hair", "白发": "white hair", "银发": "silver hair", "红发": "red hair", "蓝发": "blue hair", "粉发": "pink hair", "紫发": "purple hair", "绿发": "green hair", "橙发": "orange hair", "灰发": "gray hair", "彩虹发": "rainbow hair", "渐变发": "gradient hair", // 身材 "高个": "tall", "矮个": "short", "娇小": "petite", "高挑": "tall and slender", "苗条": "slim", "纤细": "slim", "瘦": "thin", "骨感": "skinny", "丰满": "curvy", "饱满": "voluptuous", "肉感": "plump", "匀称": "well-proportioned", "性感": "sexy", "优美": "graceful", // 胸部 "大胸": "large breasts", "巨乳": "huge breasts", "丰满": "large breasts", "小胸": "small breasts", "贫乳": "small breasts", "平胸": "flat chest", "挺拔": "perky", "坚挺": "firm", "饱满": "full", "柔软": "soft", "弹性": "bouncy", "深沟": "cleavage", // 腿部 "美腿": "beautiful legs", "长腿": "long legs", "细腿": "slender legs", "修长": "slender", "笔直": "straight", "匀称": "shapely", "大腿": "thighs", "小腿": "calves", "脚踝": "ankles", // 皮肤 "白皙": "fair", "雪白": "snow white", "透白": "translucent", "古铜": "tanned", "小麦色": "wheat colored", "健康": "healthy", "光滑": "smooth", "细腻": "delicate", "粗糙": "rough", "红润": "rosy", "苍白": "pale", "有光泽": "glowing", // 眼睛 "大眼": "big eyes", "小眼": "small eyes", "圆眼": "round eyes", "细长眼": "narrow eyes", "杏眼": "almond eyes", "桃花眼": "peach blossom eyes", "双眼皮": "double eyelids", "单眼皮": "single eyelids", "长睫毛": "long eyelashes", "浓睫毛": "thick eyelashes", // 特殊特征 "猫耳": "cat ears", "狐耳": "fox ears", "兔耳": "bunny ears", "狼耳": "wolf ears", "犬耳": "dog ears", "精灵耳": "elf ears", "翅膀": "wings", "天使翅膀": "angel wings", "恶魔翅膀": "demon wings", "尾巴": "tail", "猫尾": "cat tail", "狐尾": "fox tail", "角": "horns", "恶魔角": "demon horns", "独角": "unicorn horn", // 体格 "肌肉": "muscular", "强壮": "muscular", "健美": "athletic", "结实": "sturdy", "精瘦": "lean", "厚实": "solid", "柔弱": "delicate", "纤弱": "fragile", "娇弱": "frail", // 面部特征 "圆脸": "round face", "瓜子脸": "oval face", "方脸": "square face", "鹅蛋脸": "oval face", "心形脸": "heart-shaped face", "高鼻梁": "high nose bridge", "小鼻子": "small nose", "厚嘴唇": "thick lips", "薄嘴唇": "thin lips", "樱桃嘴": "cherry lips", "尖下巴": "pointed chin", "圆下巴": "round chin", "酒窝": "dimples", "笑容": "smile", "梨涡": "dimples", // 其他 "胡子": "beard", "胡须": "mustache", "络腮胡": "full beard", "光头": "bald", "秃头": "bald", "寸头": "buzz cut", "疤痕": "scar", "纹身": "tattoo", "胎记": "birthmark", "雀斑": "freckles", "痣": "mole", "美人痣": "beauty mark", "虎牙": "fangs", "小虎牙": "small fangs" }, expressions: { // 快乐情绪 "微笑": "smile", "笑": "smile", "开心": "happy", "高兴": "happy", "大笑": "laughing", "窃笑": "giggling", "傻笑": "silly smile", "甜笑": "sweet smile", "温和笑": "gentle smile", "灿烂笑": "bright smile", "兴奋": "excited", "激动": "excited", "愉快": "cheerful", "欣喜": "delighted", "狂喜": "ecstatic", "满意": "satisfied", // 悲伤情绪 "伤心": "sad", "难过": "sad", "哭": "crying", "流泪": "tears", "大哭": "sobbing", "抽泣": "sniffling", "眼泪汪汪": "teary eyes", "悲伤": "sorrowful", "沮丧": "depressed", "失落": "disappointed", "绝望": "despair", "痛苦": "painful", "心碎": "heartbroken", // 愤怒情绪 "生气": "angry", "愤怒": "angry", "恼火": "angry", "暴怒": "furious", "发火": "mad", "气愤": "indignant", "不满": "dissatisfied", "抱怨": "complaining", "怨恨": "resentful", // 害羞情绪 "害羞": "shy", "脸红": "blushing", "羞涩": "shy", "害臊": "bashful", "腼腆": "timid", "不好意思": "embarrassed", "羞耻": "ashamed", "窘迫": "flustered", "局促": "awkward", // 惊讶情绪 "惊讶": "surprised", "吃惊": "surprised", "震惊": "shocked", "惊愕": "astonished", "惊恐": "horrified", "目瞪口呆": "stunned", "困惑": "confused", "疑惑": "puzzled", "迷茫": "bewildered", // 温柔情绪 "温柔": "gentle", "柔和": "gentle", "亲切": "gentle", "慈祥": "kind", "和善": "friendly", "温暖": "warm", "关爱": "caring", "怜爱": "tender", "宠溺": "doting", // 严肃情绪 "严肃": "serious", "认真": "serious", "冷静": "calm", "严厉": "stern", "冷漠": "indifferent", "无表情": "expressionless", "冷酷": "cold", "淡漠": "aloof", "疏远": "distant", // 疲倦情绪 "困": "sleepy", "累": "tired", "疲倦": "tired", "疲惫": "exhausted", "困倦": "drowsy", "无精打采": "listless", "虚弱": "weak", "萎靡": "dispirited", "懒散": "lazy", // 其他情绪 "紧张": "nervous", "担心": "worried", "焦虑": "anxious", "恐惧": "fearful", "害怕": "scared", "胆怯": "timid", "自信": "confident", "骄傲": "proud", "得意": "smug", "傲慢": "arrogant", "轻蔑": "contemptuous", "不屑": "disdainful", "好奇": "curious", "感兴趣": "interested", "专注": "focused", "集中": "concentrated", "沉思": "contemplating", "思考": "thinking", "无聊": "bored", "厌倦": "tired of", "烦躁": "irritated", "期待": "expectant", "渴望": "longing", "向往": "yearning" }, poses: { // 基础姿势 "站着": "standing", "站立": "standing", "直立": "upright", "坐着": "sitting", "坐下": "sitting", "端坐": "sitting properly", "躺着": "lying", "躺下": "lying", "平躺": "lying flat", "跪着": "kneeling", "下跪": "kneeling", "跪坐": "seiza", "蹲着": "squatting", "蹲下": "crouching", "半蹲": "half squat", // 动作姿势 "走路": "walking", "行走": "walking", "漫步": "strolling", "跑步": "running", "奔跑": "running", "疾跑": "sprinting", "跳跃": "jumping", "蹦跳": "hopping", "飞跃": "leaping", "跳舞": "dancing", "舞蹈": "dancing", "旋转": "spinning", "伸展": "stretching", "弯腰": "bending", "下腰": "backbend", // 手部动作 "举手": "arms up", "抬手": "arms up", "双手举起": "both arms up", "伸手": "reaching out", "指向": "pointing", "挥手": "waving", "鼓掌": "clapping", "握拳": "clenched fist", "比心": "heart gesture", "捂脸": "covering face", "托腮": "chin rest", "撑头": "head rest", // 互动姿势 "拥抱": "hugging", "抱着": "hugging", "搂抱": "embracing", "牵手": "holding hands", "握手": "handshake", "搀扶": "supporting", "背着": "carrying on back", "抱起": "lifting up", "搂腰": "arm around waist", // 生活姿势 "睡觉": "sleeping", "熟睡": "sleeping", "打盹": "napping", "看书": "reading", "阅读": "reading", "翻书": "turning pages", "写字": "writing", "书写": "writing", "画画": "drawing", "工作": "working", "学习": "studying", "思考": "thinking", "做作业": "homework", "写作业": "homework", "考试": "taking exam", // 运动姿势 "游泳": "swimming", "潜水": "diving", "跳水": "diving", "爬山": "climbing", "攀登": "climbing", "攀岩": "rock climbing", "骑车": "cycling", "开车": "driving", "骑马": "horseback riding", "滑雪": "skiing", "滑冰": "ice skating", "溜冰": "skating", "健身": "exercising", "瑜伽": "yoga", "拉伸": "stretching", // 战斗姿势 "战斗": "fighting", "格斗": "combat", "对战": "battle", "攻击": "attacking", "防御": "defending", "出拳": "punching", "踢腿": "kicking", "挥剑": "sword swinging", "射箭": "archery", // 表演姿势 "唱歌": "singing", "演奏": "playing instrument", "表演": "performing", "朗诵": "reciting", "演讲": "giving speech", "主持": "hosting", // 特殊姿势 "冥想": "meditation", "祈祷": "praying", "许愿": "making wish", "仰望": "looking up", "俯视": "looking down", "回首": "looking back", "侧身": "side view", "背影": "back view", "正面": "front view", "倚靠": "leaning", "靠墙": "leaning against wall", "趴着": "lying on stomach" }, locations: { // 居住场所 "卧室": "bedroom", "房间": "bedroom", "寝室": "bedroom", "客厅": "living room", "起居室": "living room", "大厅": "hall", "厨房": "kitchen", "灶间": "kitchen", "餐厅": "dining room", "浴室": "bathroom", "洗手间": "bathroom", "厕所": "toilet", "阳台": "balcony", "露台": "terrace", "庭院": "courtyard", "花园": "garden", "后院": "backyard", "前院": "front yard", "地下室": "basement", "阁楼": "attic", "储藏室": "storage room", // 学校场所 "教室": "classroom", "课堂": "classroom", "学校": "school", "图书馆": "library", "书馆": "library", "阅览室": "reading room", "实验室": "laboratory", "研究室": "laboratory", "计算机房": "computer room", "体育馆": "gymnasium", "操场": "playground", "运动场": "sports field", "食堂": "cafeteria", "宿舍": "dormitory", "社团室": "club room", "校园": "campus", "校门": "school gate", "走廊": "corridor", // 工作场所 "办公室": "office", "工作室": "office", "会议室": "meeting room", "公司": "company", "企业": "corporation", "工厂": "factory", "车间": "workshop", "仓库": "warehouse", "商店": "shop", "超市": "supermarket", "商场": "shopping mall", "市场": "market", "银行": "bank", "邮局": "post office", "政府": "government office", // 医疗场所 "医院": "hospital", "诊所": "hospital", "急诊室": "emergency room", "病房": "hospital room", "手术室": "operating room", "药房": "pharmacy", // 娱乐场所 "咖啡厅": "cafe", "咖啡店": "cafe", "茶馆": "tea house", "餐厅": "restaurant", "饭店": "restaurant", "快餐店": "fast food", "酒吧": "bar", "夜店": "nightclub", "KTV": "karaoke", "电影院": "cinema", "剧院": "theater", "音乐厅": "concert hall", "游乐园": "amusement park", "动物园": "zoo", "水族馆": "aquarium", "博物馆": "museum", "美术馆": "art gallery", "展览馆": "exhibition hall", // 自然场所 "公园": "park", "广场": "square", "街道": "street", "海边": "beach", "沙滩": "beach", "海滩": "beach", "森林": "forest", "树林": "forest", "丛林": "jungle", "山": "mountain", "高山": "mountain", "山顶": "mountain peak", "湖边": "lake", "湖泊": "lake", "河边": "riverside", "河流": "river", "溪流": "stream", "瀑布": "waterfall", "草原": "grassland", "田野": "field", "农场": "farm", "沙漠": "desert", "雪山": "snowy mountain", "冰川": "glacier", // 交通场所 "火车站": "train station", "地铁站": "subway station", "公交站": "bus stop", "机场": "airport", "港口": "port", "码头": "dock", "停车场": "parking lot", "加油站": "gas station", // 宗教场所 "教堂": "church", "寺庙": "temple", "清真寺": "mosque", "神社": "shrine", "修道院": "monastery", // 特殊场所 "城堡": "castle", "宫殿": "castle", "塔楼": "tower", "桥": "bridge", "大桥": "bridge", "隧道": "tunnel", "屋顶": "rooftop", "天台": "rooftop", "楼顶": "rooftop", "地铁": "subway", "电梯": "elevator", "楼梯": "stairs", "监狱": "prison", "法院": "courthouse", "警察局": "police station", "温泉": "hot spring", "海岛": "island", "洞穴": "cave", "废墟": "ruins", "遗迹": "ruins", "秘境": "secret place" }, weather_time: { // 天气 "晴天": "sunny", "阳光": "sunny", "晴朗": "sunny", "多云": "cloudy", "阴天": "cloudy", "乌云": "dark clouds", "下雨": "rain", "雨天": "rainy", "雨": "rain", "毛毛雨": "drizzle", "大雨": "heavy rain", "暴雨": "storm", "雷雨": "thunderstorm", "闪电": "lightning", "打雷": "thunder", "下雪": "snow", "雪天": "snowy", "雪": "snow", "暴雪": "blizzard", "雪花": "snowflakes", "雪景": "snowy scene", "雾": "fog", "薄雾": "mist", "浓雾": "thick fog", "风": "wind", "微风": "breeze", "强风": "strong wind", "台风": "typhoon", "龙卷风": "tornado", "沙尘暴": "sandstorm", // 时间 "日出": "sunrise", "清晨": "morning", "早晨": "morning", "上午": "morning", "中午": "noon", "下午": "afternoon", "日落": "sunset", "黄昏": "sunset", "夕阳": "sunset", "傍晚": "evening", "夜晚": "night", "晚上": "night", "深夜": "night", "午夜": "midnight", "凌晨": "dawn", "白天": "day", "日间": "day", "夜间": "night", // 季节 "春天": "spring", "春季": "spring", "初春": "early spring", "夏天": "summer", "夏季": "summer", "盛夏": "midsummer", "秋天": "autumn", "秋季": "autumn", "深秋": "late autumn", "冬天": "winter", "冬季": "winter", "隆冬": "midwinter", // 天象 "月光": "moonlight", "满月": "full moon", "新月": "new moon", "星空": "starry sky", "繁星": "stars", "银河": "milky way", "彩虹": "rainbow", "双彩虹": "double rainbow", "流星": "meteor", "日食": "solar eclipse", "月食": "lunar eclipse", "极光": "aurora", // 气候 "炎热": "hot", "温暖": "warm", "凉爽": "cool", "寒冷": "cold", "冰冷": "freezing", "严寒": "bitter cold", "潮湿": "humid", "干燥": "dry", "闷热": "muggy" }, colors: { // 基础颜色 "红色": "red", "红": "red", "朱红": "red", "深红": "dark red", "粉色": "pink", "粉红": "pink", "粉": "pink", "浅粉": "light pink", "橙色": "orange", "橘色": "orange", "橙": "orange", "橘红": "red orange", "黄色": "yellow", "黄": "yellow", "金黄": "golden yellow", "柠檬黄": "lemon yellow", "绿色": "green", "绿": "green", "翠绿": "emerald green", "深绿": "dark green", "蓝色": "blue", "蓝": "blue", "天蓝": "sky blue", "深蓝": "dark blue", "紫色": "purple", "紫": "purple", "紫罗兰": "violet", "深紫": "dark purple", "黑色": "black", "黑": "black", "乌黑": "jet black", "深黑": "deep black", "白色": "white", "白": "white", "洁白": "pure white", "雪白": "snow white", "灰色": "gray", "灰": "gray", "银灰": "silver gray", "深灰": "dark gray", "棕色": "brown", "褐色": "brown", "咖啡色": "coffee brown", "巧克力色": "chocolate", // 金属色 "银色": "silver", "金色": "gold", "铜色": "copper", "青铜": "bronze", "铂金": "platinum", "玫瑰金": "rose gold", // 特殊色彩 "彩虹色": "rainbow", "渐变色": "gradient", "透明": "transparent", "荧光": "fluorescent", "金属": "metallic", "珠光": "pearl", "哑光": "matte", "亮光": "glossy", "闪光": "glitter" }, objects: { // 书籍文具 "书": "book", "书本": "book", "图书": "book", "小说": "novel", "教科书": "textbook", "字典": "dictionary", "杂志": "magazine", "笔": "pen", "钢笔": "fountain pen", "铅笔": "pencil", "毛笔": "brush pen", "纸": "paper", "笔记本": "notebook", "日记": "diary", "便签": "sticky note", // 花卉植物 "花": "flower", "鲜花": "flower", "花朵": "flower", "花束": "bouquet", "玫瑰": "rose", "樱花": "cherry blossom", "向日葵": "sunflower", "郁金香": "tulip", "百合": "lily", "菊花": "chrysanthemum", "树": "tree", "盆栽": "potted plant", "仙人掌": "cactus", // 餐具茶具 "杯子": "cup", "茶杯": "teacup", "咖啡杯": "coffee cup", "水杯": "water glass", "酒杯": "wine glass", "马克杯": "mug", "盘子": "plate", "碗": "bowl", "勺子": "spoon", "叉子": "fork", "筷子": "chopsticks", "刀": "knife", "茶壶": "teapot", // 装饰品 "镜子": "mirror", "时钟": "clock", "钟": "clock", "闹钟": "alarm clock", "相框": "photo frame", "画": "painting", "海报": "poster", "蜡烛": "candle", "台灯": "desk lamp", "花瓶": "vase", // 武器道具 "剑": "sword", "刀": "sword", "匕首": "dagger", "长矛": "spear", "弓": "bow", "箭": "arrow", "盾": "shield", "铠甲": "armor", "魔法棒": "magic wand", "法杖": "staff", "水晶球": "crystal ball", // 乐器 "吉他": "guitar", "钢琴": "piano", "小提琴": "violin", "笛子": "flute", "鼓": "drum", "萨克斯": "saxophone", // 电子设备 "电脑": "computer", "笔记本": "laptop", "平板": "tablet", "手机": "phone", "相机": "camera", "照相机": "camera", "电视": "television", "收音机": "radio", "耳机": "headphones", // 日用品 "伞": "umbrella", "雨伞": "umbrella", "遮阳伞": "parasol", "包": "bag", "书包": "bag", "手提包": "handbag", "背包": "backpack", "钱包": "wallet", "钥匙": "key", "锁": "lock", "枕头": "pillow", "抱枕": "pillow", "毯子": "blanket", "被子": "quilt", "床单": "bedsheet", "毛巾": "towel", // 交通工具 "汽车": "car", "自行车": "bicycle", "摩托车": "motorcycle", "公交车": "bus", "出租车": "taxi", "卡车": "truck", "飞机": "airplane", "直升机": "helicopter", "船": "ship", "游艇": "yacht", "火车": "train", "地铁": "subway", // 食物饮品 "咖啡": "coffee", "茶": "tea", "水": "water", "果汁": "juice", "蛋糕": "cake", "面包": "bread", "饼干": "cookie", "苹果": "apple", "香蕉": "banana", "橙子": "orange", "巧克力": "chocolate", "糖果": "candy", "冰淇淋": "ice cream", // 首饰配件 "项链": "necklace", "手链": "bracelet", "戒指": "ring", "耳环": "earrings", "胸针": "brooch", "手表": "watch", "皇冠": "crown", "头饰": "hair accessory", "发卡": "hair clip", // 运动用品 "球": "ball", "篮球": "basketball", "足球": "soccer ball", "网球": "tennis ball", "乒乓球": "ping pong ball", "球拍": "racket", "滑板": "skateboard", "轮滑鞋": "roller skates", // 玩具 "玩偶": "doll", "泰迪熊": "teddy bear", "毛绒玩具": "stuffed animal", "积木": "building blocks", "拼图": "puzzle", "棋": "chess", "扑克": "playing cards", "骰子": "dice", "风筝": "kite" }, styles: { // 美感风格 "可爱": "cute", "美丽": "beautiful", "漂亮": "pretty", "美": "beautiful", "绝美": "stunning", "惊艳": "gorgeous", "优雅": "elegant", "高贵": "noble", "华丽": "gorgeous", "精致": "delicate", "完美": "perfect", "迷人": "charming", // 性感风格 "性感": "sexy", "诱惑": "seductive", "魅惑": "seductive", "撩人": "alluring", "火辣": "hot", "妖娆": "enchanting", "风情": "charming", "妩媚": "seductive", "勾人": "alluring", // 纯真风格 "清纯": "innocent", "纯洁": "pure", "天真": "innocent", "单纯": "naive", "纯真": "pure", "清新": "fresh", "自然": "natural", "朴素": "simple", "清雅": "elegant", // 成熟风格 "成熟": "mature", "稳重": "mature", "知性": "intellectual", "干练": "capable", "职业": "professional", "严谨": "rigorous", "端庄": "dignified", "庄重": "solemn", "典雅": "elegant", // 活力风格 "活泼": "lively", "开朗": "cheerful", "阳光": "bright", "青春": "youthful", "朝气": "energetic", "活力": "vibrant", "热情": "passionate", "积极": "positive", "乐观": "optimistic", // 冷酷风格 "神秘": "mysterious", "冷酷": "cool", "高冷": "cold", "冰冷": "icy", "冷漠": "indifferent", "疏离": "distant", "孤独": "lonely", "忧郁": "melancholy", "深沉": "deep", // 温暖风格 "温暖": "warm", "舒适": "comfortable", "宁静": "peaceful", "温和": "gentle", "慈祥": "kind", "亲切": "friendly", "贴心": "caring", "体贴": "considerate", "善良": "kind", // 浪漫风格 "浪漫": "romantic", "梦幻": "dreamy", "唯美": "aesthetic", "诗意": "poetic", "文艺": "artistic", "小清新": "fresh", "治愈": "healing", "暖心": "heartwarming", "甜美": "sweet", // 奇幻风格 "奇幻": "fantasy", "魔幻": "magical", "神秘": "mysterious", "超现实": "surreal", "梦境": "dreamlike", "虚幻": "illusory", // 时代风格 "古典": "classic", "复古": "vintage", "古风": "ancient style", "现代": "modern", "时尚": "fashionable", "前卫": "avant-garde", "未来": "futuristic", "科幻": "sci-fi", "赛博朋克": "cyberpunk", // 男性魅力 "帅气": "handsome", "英俊": "handsome", "潇洒": "dashing", "俊美": "handsome", "阳刚": "masculine", "威严": "dignified", "强大": "powerful", "威猛": "mighty", "勇敢": "brave", "绅士": "gentleman", "风度": "graceful", "魅力": "charismatic", "霸气": "domineering", "王者": "kingly", "领袖": "leadership" }, activities: { // 学习活动 "学习": "studying", "上课": "attending class", "考试": "exam", "复习": "reviewing", "预习": "previewing", "做题": "solving problems", "做作业": "homework", "写作业": "homework", "背书": "memorizing", "研究": "research", "实验": "experiment", "讨论": "discussion", // 生活活动 "做饭": "cooking", "吃饭": "eating", "用餐": "dining", "喝茶": "drinking tea", "喝咖啡": "drinking coffee", "品茶": "tea tasting", "洗澡": "bathing", "沐浴": "bathing", "泡澡": "bathing", "洗漱": "washing up", "刷牙": "brushing teeth", "洗脸": "washing face", "睡觉": "sleeping", "午睡": "napping", "休息": "resting", "起床": "getting up", "醒来": "waking up", // 购物娱乐 "购物": "shopping", "逛街": "shopping", "买东西": "shopping", "逛商场": "mall shopping", "网购": "online shopping", "看电影": "watching movie", "看电视": "watching TV", "追剧": "binge watching", "听音乐": "listening to music", "唱歌": "singing", "唱K": "karaoke", "游戏": "gaming", "玩耍": "playing", "娱乐": "entertainment", "聊天": "chatting", "谈话": "talking", "交流": "communicating", // 运动健身 "运动": "sports", "健身": "fitness", "锻炼": "exercise", "跑步": "running", "慢跑": "jogging", "散步": "walking", "游泳": "swimming", "潜水": "diving", "跳水": "diving", "登山": "mountain climbing", "徒步": "hiking", "骑行": "cycling", "瑜伽": "yoga", "舞蹈": "dancing", "跳舞": "dancing", "太极": "tai chi", "武术": "martial arts", "拳击": "boxing", // 工作活动 "工作": "working", "加班": "overtime", "会议": "meeting", "开会": "attending meeting", "谈判": "negotiation", "签约": "signing contract", "出差": "business trip", "培训": "training", "实习": "internship", // 社交活动 "聚会": "party", "庆祝": "celebration", "生日": "birthday", "聚餐": "group dining", "野餐": "picnic", "烧烤": "barbecue", "约会": "dating", "恋爱": "romance", "表白": "confession", "求婚": "proposal", "结婚": "wedding", "婚礼": "wedding ceremony", "蜜月": "honeymoon", "旅行": "travel", "度假": "vacation", "观光": "sightseeing", "旅游": "tourism", "探险": "adventure", // 文艺活动 "看书": "reading", "阅读": "reading", "写作": "writing", "画画": "drawing", "绘画": "painting", "摄影": "photography", "书法": "calligraphy", "雕刻": "carving", "手工": "handicraft", "编织": "knitting", "刺绣": "embroidery", "陶艺": "pottery", // 情感互动 "调戏": "teasing", "戏弄": "teasing", "挑逗": "flirting", "撩": "flirting", "撩拨": "flirting", "勾引": "seduction", "诱惑": "seduction", "魅惑": "seduction", "撒娇": "acting cute", "卖萌": "acting cute", "害羞": "shy", "脸红": "blushing", "接吻": "kissing", "亲吻": "kissing", "亲": "kissing", "拥抱": "hugging", "抱": "hugging", "搂": "embracing", "牵手": "holding hands", "握手": "handshake", "抚摸": "caressing", "爱抚": "caressing", "按摩": "massage", "安慰": "comforting", "关心": "caring", "照顾": "taking care", // 窥视相关 "偷看": "peeking", "窥视": "voyeur", "偷窥": "voyeur", "暗中观察": "secretly observing", "跟踪": "following", "展示": "showing", "炫耀": "showing off", "露出": "exposing", "表现": "performing", "演示": "demonstrating", // 梦境活动 "梦": "dreaming", "做梦": "dreaming", "梦见": "dreaming", "梦游": "sleepwalking", "噩梦": "nightmare", "美梦": "sweet dream", // 思考活动 "思考": "thinking", "考虑": "considering", "琢磨": "pondering", "沉思": "contemplating", "反思": "reflecting", "冥想": "meditation", "发呆": "daydreaming", "走神": "spacing out", "幻想": "fantasizing", // 创作活动 "创作": "creating", "发明": "inventing", "设计": "designing", "制作": "making", "建造": "building", "构建": "constructing", "修理": "repairing", "维修": "fixing", "改造": "renovating" }, body_parts: { // 头部 "头": "head", "头部": "head", "脑袋": "head", "脸": "face", "面部": "face", "容颜": "face", "额头": "forehead", "脸颊": "cheeks", "下巴": "chin", "眼睛": "eyes", "眼": "eyes", "眼神": "gaze", "目光": "gaze", "眉毛": "eyebrows", "睫毛": "eyelashes", "眼皮": "eyelids", "鼻子": "nose", "鼻": "nose", "鼻梁": "nose bridge", "嘴": "mouth", "嘴唇": "lips", "舌头": "tongue", "牙齿": "teeth", "虎牙": "fangs", "门牙": "front teeth", "耳朵": "ears", "耳": "ears", "耳垂": "earlobes", "头发": "hair", "发型": "hairstyle", "刘海": "bangs", // 颈部胸部 "脖子": "neck", "颈": "neck", "咽喉": "throat", "肩膀": "shoulders", "肩": "shoulders", "锁骨": "collarbone", "胸": "breasts", "胸部": "breasts", "乳房": "breasts", "胸膛": "chest", "胸口": "chest", "心脏": "heart", // 手臂手部 "手臂": "arms", "臂": "arms", "上臂": "upper arms", "前臂": "forearms", "肘": "elbows", "肘部": "elbows", "手": "hands", "手掌": "palms", "手背": "back of hands", "手指": "fingers", "拇指": "thumbs", "食指": "index fingers", "中指": "middle fingers", "无名指": "ring fingers", "小指": "pinky fingers", "指甲": "nails", "手腕": "wrists", "腕": "wrists", // 躯干 "身体": "body", "身材": "figure", "体型": "body type", "背": "back", "后背": "back", "脊背": "spine", "腰": "waist", "腰部": "waist", "细腰": "slim waist", "肚子": "belly", "腹部": "abdomen", "腹": "abdomen", "肚脐": "navel", "小腹": "lower abdomen", "臀部": "hips", "屁股": "butt", "臀": "buttocks", // 腿部足部 "腿": "legs", "大腿": "thighs", "小腿": "calves", "膝盖": "knees", "膝": "knees", "脚踝": "ankles", "脚": "feet", "足": "feet", "脚掌": "soles", "脚趾": "toes", "脚指": "toes", "脚跟": "heels", // 皮肤相关 "皮肤": "skin", "肌肤": "skin", "体肤": "skin", "毛孔": "pores", "汗": "sweat", "体温": "body temperature", // 内衣相关 "胸罩": "bra", "文胸": "bra", "内衣": "underwear", "内裤": "panties", "底裤": "underwear", "三角裤": "briefs", "胖次": "panties", "安全裤": "safety shorts" }, nsfw_actions: { // 基础行为 "做爱": "sex", "性爱": "sex", "交配": "mating", "性交": "intercourse", "爱爱": "making love", "啪啪": "sex", "嘿咻": "sex", // 插入动作 "插入": "penetration", "进入": "penetration", "插": "insertion", "深入": "deep penetration", "浅入": "shallow penetration", "刺入": "thrusting in", "顶入": "pushing in", // 律动动作 "抽插": "thrusting", "律动": "thrusting", "顶": "thrusting", "冲撞": "pounding", "撞击": "hitting", "摩擦": "rubbing", "研磨": "grinding", "扭动": "twisting", "起伏": "undulating", // 高潮相关 "高潮": "orgasm", "达到高潮": "climax", "巅峰": "peak", "射精": "ejaculation", "释放": "release", "爆发": "explosion", "喷": "squirting", "涌出": "gushing", "流出": "flowing", // 口部动作 "口交": "oral sex", "含": "sucking", "舔": "licking", "吸": "sucking", "吮": "sucking", "咬": "biting", "亲": "kissing", "深吻": "deep kiss", "法式接吻": "french kiss", // 体位相关 "肛交": "anal sex", "后入": "doggy style", "骑乘": "cowgirl", "传教士": "missionary", "侧位": "side position", "反向": "reverse", "站立": "standing position", "坐位": "sitting position", // 自慰相关 "手淫": "masturbation", "自慰": "masturbation", "撸": "stroking", "套弄": "stroking", "摩擦": "rubbing", "刺激": "stimulation", // 抚摸动作 "指交": "fingering", "抚弄": "fondling", "揉": "massaging", "搓": "rubbing", "捏": "pinching", "压": "pressing", "按": "pressing", "推": "pushing", "拉": "pulling", // 体液相关 "爱液": "love juice", "精液": "semen", "体液": "bodily fluids", "分泌": "secretion", "润滑": "lubrication", "湿润": "moisture", // 状态描述 "湿润": "wet", "润滑": "lubricated", "干燥": "dry", "紧": "tight", "松": "loose", "深": "deep", "浅": "shallow", "热": "hot", "温暖": "warm", "冰凉": "cold", "快": "fast", "慢": "slow", "用力": "hard", "轻": "gentle", "粗暴": "rough", "温柔": "gentle", "激烈": "intense", "缓慢": "slow" }, nsfw_body_parts: { // 男性器官 "阴茎": "penis", "鸡巴": "cock", "肉棒": "dick", "老二": "dick", "鸡鸡": "penis", "小弟弟": "penis", "那话儿": "penis", "龟头": "glans", "包皮": "foreskin", "马眼": "urethral opening", "睾丸": "testicles", "蛋蛋": "balls", "精囊": "seminal vesicles", // 女性器官 "阴道": "vagina", "小穴": "pussy", "阴唇": "labia", "花瓣": "labia", "阴蒂": "clitoris", "豆豆": "clitoris", "小核": "clitoris", "阴户": "vulva", "私处": "private parts", "花径": "vagina", "子宫": "womb", "宫口": "cervix", "G点": "g-spot", "敏感点": "sensitive spot", // 共同部位 "肛门": "anus", "菊花": "asshole", "后庭": "backdoor", "屁眼": "butthole", "会阴": "perineum", "下体": "genitals", "性器": "sex organ", "私密处": "intimate parts", "敏感带": "erogenous zone", // 胸部 "乳头": "nipples", "奶头": "nipples", "乳晕": "areola", "奶子": "tits", "胸脯": "breasts", "酥胸": "soft breasts", "双峰": "twin peaks", "玉兔": "breasts", "雪峰": "white breasts", // 其他敏感部位 "大腿根": "inner thighs", "腿间": "between legs", "股间": "crotch", "后穴": "back hole", "前穴": "front hole", "蜜穴": "honey pot", "花心": "deep inside", "花芯": "core", "深处": "deep inside", // 生理反应 "勃起": "erection", "坚挺": "stiff", "充血": "engorged", "湿润": "wet", "分泌": "secreting", "流水": "dripping", "收缩": "contracting", "痉挛": "spasming", "颤抖": "trembling", // 特殊词汇 "前列腺": "prostate", "尿道": "urethra", "处女膜": "hymen", "欲火": "lust", "春情": "arousal", "情欲": "passion" }, nsfw_states: { // 男性状态 "勃起": "erect", "硬": "hard", "坚挺": "stiff", "挺立": "standing", "半勃": "semi-erect", "软": "soft", "疲软": "limp", "胀大": "swollen", "充血": "engorged", "青筋暴起": "veiny", // 女性状态 "湿": "wet", "潮湿": "moist", "流水": "dripping", "湿润": "lubricated", "干涩": "dry", "紧致": "tight", "松弛": "loose", "夹紧": "clenching", "收缩": "contracting", "痉挛": "spasming", // 共同状态 "胀": "swollen", "肿": "enlarged", "充血": "engorged", "敏感": "sensitive", "酥麻": "tingling", "颤抖": "trembling", "战栗": "shivering", "痉挛": "convulsing", "抽搐": "twitching", // 情绪状态 "兴奋": "aroused", "激动": "excited", "冲动": "horny", "发情": "in heat", "春心荡漾": "aroused", "欲火焚身": "lustful", "欲火": "lustful", "渴望": "craving", "饥渴": "thirsty", "急需": "desperate", "忍耐": "enduring", "煎熬": "suffering", // 满足状态 "满足": "satisfied", "充实": "fulfilled", "空虚": "empty", "饱满": "full", "撑胀": "stretched", "填满": "filled", "深入": "deep", "顶到": "hitting", "碰到": "touching", // 感觉状态 "疼": "painful", "痛": "aching", "酸": "sore", "爽": "pleasurable", "舒服": "comfortable", "快感": "pleasure", "酥": "tingling", "麻": "numb", "痒": "itchy", "热": "hot", "烫": "burning", "凉": "cool", "涨": "swelling", "胀": "bloated", "紧": "tight", // 程度状态 "轻微": "slight", "强烈": "intense", "剧烈": "violent", "温和": "gentle", "激烈": "fierce", "疯狂": "crazy", "缓慢": "slow", "急促": "rapid", "持续": "continuous" }, nsfw_sounds: { // 呻吟声 "呻吟": "moaning", "叫床": "moaning", "娇喘": "panting", "喘息": "breathing heavily", "急喘": "panting", "粗喘": "heavy breathing", // 基础音节 "哼": "humming", "嗯": "mmm", "唔": "mmm", "啊": "ah", "哦": "oh", "噢": "oh", "嘤": "whimpering", "嘤嘤": "whimpering", "嘤嘤嘤": "whimpering", // 高音调 "尖叫": "screaming", "尖声": "high-pitched", "细声": "thin voice", "呼喊": "crying out", "大叫": "shouting", "惊叫": "exclaiming", // 低音调 "低吟": "groaning", "闷哼": "muffled moan", "低喃": "mumbling", "嘟囔": "muttering", "咕哝": "grumbling", "轻哼": "soft humming", // 情绪音 "啜泣": "sobbing", "哽咽": "choking", "抽泣": "sniffling", "颤音": "trembling voice", "破音": "voice breaking", // 生理音 "喘气": "gasping", "倒抽气": "sharp intake", "屏息": "holding breath", "换气": "catching breath", "深呼吸": "deep breathing", // 其他音效 "叫声": "vocal", "声音": "sounds", "噪音": "noise", "音调": "tone", "音量": "volume", "回音": "echo", "轻声": "whisper", "细语": "soft voice", "耳语": "whispering", "颤抖": "trembling", "战栗": "shivering", "哆嗦": "quivering" }, nsfw_descriptions: { // 基础描述 "色情": "pornographic", "淫荡": "lewd", "下流": "vulgar", "猥亵": "obscene", "淫秽": "indecent", "不雅": "improper", "淫乱": "promiscuous", "放荡": "wanton", "骚": "slutty", "浪": "naughty", "风骚": "seductive", "妖艳": "bewitching", // 性格特征 "骚货": "slut", "淫娃": "sex kitten", "小妖精": "little minx", "小浪蹄子": "little slut", "狐狸精": "vixen", "妖女": "seductress", "处女": "virgin", "纯洁": "pure", "清纯": "innocent", "无辜": "innocent", "天真": "naive", "单纯": "simple", // 经验程度 "经验": "experienced", "老练": "skilled", "熟练": "proficient", "熟女": "mature woman", "老司机": "experienced", "新手": "beginner", "生涩": "inexperienced", "青涩": "green", "稚嫩": "tender", // 特殊嗜好 "禁忌": "taboo", "变态": "pervert", "扭曲": "twisted", "病态": "sick", "不正常": "abnormal", "特殊": "special", "癖好": "fetish", "嗜好": "preference", "口味": "taste", // 权力关系 "调教": "training", "驯服": "taming", "征服": "conquering", "支配": "domination", "统治": "ruling", "控制": "control", "服从": "submission", "屈服": "yielding", "顺从": "obedient", "奴隶": "slave", "奴": "slave", "宠物": "pet", "主人": "master", "主": "master", "女王": "queen", "女主": "mistress", "王": "king", "君主": "sovereign", // 强度描述 "轻柔": "gentle", "温和": "mild", "激烈": "intense", "粗暴": "rough", "野蛮": "savage", "狂野": "wild", "疯狂": "crazy", "极端": "extreme", "过分": "excessive" }, intimate_settings: { // 私密场所 "床": "bed", "床上": "on bed", "大床": "big bed", "单人床": "single bed", "双人床": "double bed", "水床": "waterbed", "床单": "bedsheet", "被子": "blanket", "枕头": "pillow", "被窝": "under blanket", "毯子": "blanket", "软垫": "soft mat", // 卧室环境 "卧室": "bedroom", "主卧": "master bedroom", "客房": "guest room", "宿舍": "dormitory", "公寓": "apartment", "套房": "suite", "酒店房间": "hotel room", "民宿": "bed and breakfast", // 浴室场所 "浴室": "bathroom", "洗手间": "bathroom", "淋浴间": "shower room", "浴缸": "bathtub", "按摩浴缸": "jacuzzi", "淋浴": "shower", "蒸汽浴": "steam bath", "桑拿": "sauna", "温泉": "hot spring", // 客厅家具 "沙发": "sofa", "长沙发": "couch", "皮沙发": "leather sofa", "躺椅": "recliner", "懒人椅": "lazy chair", "摇椅": "rocking chair", "地毯": "carpet", "地垫": "mat", "地板": "floor", "茶几": "coffee table", "边桌": "side table", // 其他家具 "桌子": "table", "书桌": "desk", "梳妆台": "dressing table", "椅子": "chair", "办公椅": "office chair", "吧台椅": "bar stool", "墙": "wall", "墙角": "corner", "窗台": "windowsill", "阳台": "balcony", "露台": "terrace", "天台": "rooftop", // 交通工具 "车里": "in car", "后座": "back seat", "驾驶座": "driver seat", "副驾驶": "passenger seat", "货车": "truck", "面包车": "van", "火车": "train", "飞机": "airplane", "游艇": "yacht", // 户外场所 "野外": "outdoors", "森林": "forest", "树林": "woods", "海滩": "beach", "沙滩": "sandy beach", "海边": "seaside", "草地": "grassland", "花园": "garden", "公园": "park", "山顶": "mountain top", "山洞": "cave", "帐篷": "tent", // 特殊场所 "办公室": "office", "会议室": "meeting room", "储藏室": "storage room", "教室": "classroom", "图书馆": "library", "实验室": "laboratory", "厕所": "toilet", "洗手间": "restroom", "更衣室": "changing room", "试衣间": "fitting room", "化妆间": "dressing room", "健身房": "gym", "瑜伽室": "yoga room", "舞蹈室": "dance studio", // 住宿场所 "酒店": "hotel", "旅馆": "motel", "民宿": "guesthouse", "度假村": "resort", "别墅": "villa", "小屋": "cabin", "招待所": "hostel", "青旅": "youth hostel" }, fetish_categories: { // 服装恋物 "丝袜": "stockings", "黑丝": "black stockings", "白丝": "white stockings", "连裤袜": "pantyhose", "网袜": "fishnet stockings", "过膝袜": "thigh highs", "高跟鞋": "high heels", "靴子": "boots", "长靴": "knee boots", "制服": "uniform", "学生装": "school uniform", "护士装": "nurse outfit", "女仆装": "maid outfit", "空姐装": "flight attendant uniform", // 材质恋物 "蕾丝": "lace", "真丝": "silk", "缎子": "satin", "皮革": "leather", "乳胶": "latex", "橡胶": "rubber", "PVC": "pvc", "金属": "metal", "链条": "chain", // 束缚用具 "束缚": "bondage", "绳子": "rope", "绳索": "rope", "手铐": "handcuffs", "脚镣": "shackles", "锁链": "chains", "眼罩": "blindfold", "口球": "gag", "项圈": "collar", "皮带": "belt", "背带": "harness", "束身衣": "corset", // 调教用具 "鞭子": "whip", "皮鞭": "leather whip", "马鞭": "riding crop", "板子": "paddle", "藤条": "cane", "羽毛": "feather", "蜡烛": "candle", "蜡油": "wax", "冰块": "ice", "夹子": "clamps", "乳夹": "nipple clamps", "刑具": "torture device", // 情趣用品 "玩具": "toy", "按摩棒": "vibrator", "震动棒": "vibrator", "假阳具": "dildo", "双头龙": "double dildo", "仿真器": "realistic toy", "跳蛋": "bullet vibrator", "遥控器": "remote control", "震动器": "vibrator", "肛塞": "butt plug", "前列腺": "prostate massager", "扩张器": "dilator", "充气娃娃": "sex doll", "飞机杯": "masturbator", "倒模": "pocket pussy", // 特殊恋物 "触手": "tentacle", "怪物": "monster", "野兽": "beast", "异形": "alien", "机器人": "robot", "人偶": "doll", "机器": "machine", "机械": "mechanical", "人工": "artificial", "科技": "technology", "虚拟": "virtual", "全息": "holographic", // 材质特殊 "毛绒": "fur", "羽毛": "feather", "丝绸": "silk", "天鹅绒": "velvet", "绒毛": "fuzzy", "光滑": "smooth", "粗糙": "rough", "硬质": "hard", "软质": "soft" }, body_modifications: { // 纹身类型 "纹身": "tattoo", "刺青": "tattoo", "花臂": "sleeve tattoo", "图腾": "tribal tattoo", "文字": "text tattoo", "图案": "pattern tattoo", "彩绘": "body painting", "临时纹身": "temporary tattoo", "传统纹身": "traditional tattoo", "日式纹身": "japanese tattoo", // 穿孔类型 "穿孔": "piercing", "打洞": "piercing", "耳洞": "ear piercing", "鼻环": "nose ring", "唇环": "lip ring", "舌环": "tongue piercing", "肚脐环": "navel piercing", "乳环": "nipple piercing", "私处穿孔": "genital piercing", "眉环": "eyebrow piercing", // 自然标记 "疤痕": "scar", "伤疤": "scar", "刀疤": "knife scar", "胎记": "birthmark", "痣": "mole", "黑痣": "dark mole", "雀斑": "freckles", "斑点": "spots", "色斑": "pigmentation", "美人痣": "beauty mark", "泪痣": "tear mole", // 肌肉特征 "肌肉": "muscle", "腹肌": "abs", "六块腹肌": "six pack", "八块腹肌": "eight pack", "人鱼线": "v-line", "马甲线": "ab line", "肱二头肌": "biceps", "胸肌": "pectoral muscles", "背肌": "back muscles", "臀肌": "glutes", "大腿肌": "thigh muscles", "小腿肌": "calf muscles", // 骨骼特征 "锁骨": "collarbone", "肩胛骨": "shoulder blade", "脊椎": "spine", "肋骨": "ribs", "髋骨": "hip bone", "颧骨": "cheekbone", "下颌": "jawline", "尖下巴": "pointed chin", "方下巴": "square jaw", // 身体凹陷 "腰窝": "dimples", "酒窝": "dimples", "梨涡": "dimples", "锁骨窝": "collarbone hollow", "太阳穴": "temples", "颈窝": "neck hollow", "脚踝窝": "ankle hollow", // 特殊特征 "虎牙": "fangs", "小虎牙": "small fangs", "门牙": "front teeth", "双眼皮": "double eyelids", "单眼皮": "single eyelids", "卧蚕": "aegyo sal", "眼袋": "eye bags", "鱼尾纹": "crow's feet", "法令纹": "nasolabial folds", "颈纹": "neck lines" }, clothing_states: { // 脱衣状态 "裸体": "nude", "全裸": "completely nude", "一丝不挂": "stark naked", "半裸": "topless", "上身裸体": "topless", "下身裸体": "bottomless", "微露": "slightly exposed", "若隐若现": "faintly visible", // 穿着状态 "穿戴整齐": "fully dressed", "衣冠楚楚": "well-dressed", "衣衫不整": "disheveled", "衣不蔽体": "barely clothed", "衣衫褴褛": "ragged clothes", "破烂": "tattered", // 材质状态 "透明": "transparent", "半透明": "see-through", "透视": "see-through", "薄": "thin", "厚": "thick", "轻薄": "light", "厚重": "heavy", "柔软": "soft", "粗糙": "rough", "光滑": "smooth", "有光泽": "glossy", "无光": "matte", // 合身程度 "紧身": "tight", "贴身": "form-fitting", "修身": "slim-fit", "宽松": "loose", "肥大": "oversized", "合身": "well-fitted", "过大": "too big", "过小": "too small", "刚好": "just right", // 长度状态 "短": "short", "超短": "very short", "迷你": "mini", "长": "long", "超长": "very long", "及地": "floor-length", "中等": "medium", "标准": "standard", "正常": "normal", // 暴露程度 "露": "exposed", "露出": "showing", "展示": "displaying", "暴露": "revealing", "性感": "sexy", "保守": "conservative", "大胆": "bold", "开放": "open", "含蓄": "modest", "若隐若现": "peek-a-boo", "欲盖弥彰": "teasingly covered", // 穿脱动作 "脱": "undressing", "脱下": "taking off", "褪去": "removing", "穿": "dressing", "穿上": "putting on", "套": "slipping on", "换": "changing", "更衣": "changing clothes", "试穿": "trying on", "扯": "pulling", "撕": "tearing", "剪": "cutting", // 衣物状态 "破": "torn", "破洞": "holes", "开口": "opening", "裂缝": "crack", "撕裂": "ripped", "磨损": "worn", "湿": "wet", "潮湿": "damp", "浸湿": "soaked", "干": "dry", "干燥": "dried", "干净": "clean", "脏": "dirty", "污": "stained", "染色": "colored", "乱": "messy", "凌乱": "disheveled", "整齐": "neat", "皱": "wrinkled", "平整": "smooth", "熨烫": "ironed" }, romance_keywords: { // 关系称谓 "恋人": "lovers", "情侣": "couple", "爱侣": "lovers", "男友": "boyfriend", "女友": "girlfriend", "伴侣": "partner", "爱人": "lover", "心上人": "sweetheart", "意中人": "beloved", "真爱": "true love", "挚爱": "beloved", "最爱": "favorite", // 恋爱类型 "初恋": "first love", "暗恋": "crush", "单恋": "unrequited love", "热恋": "passionate love", "苦恋": "painful love", "禁恋": "forbidden love", "师生恋": "teacher-student romance", "办公室恋情": "office romance", "远距离恋爱": "long distance relationship", "网恋": "online romance", // 情感状态 "心动": "heartbeat", "怦然心动": "heart racing", "一见钟情": "love at first sight", "脸红心跳": "blushing", "心跳加速": "racing heart", "心如鹿撞": "heart pounding", "心花怒放": "heart blooming", "心潮澎湃": "surging emotions", "情不自禁": "can't help oneself", "难以自拔": "unable to extricate", // 甜蜜情感 "甜蜜": "sweet", "温馨": "warm", "浪漫": "romantic", "幸福": "happy", "快乐": "joyful", "满足": "satisfied", "陶醉": "intoxicated", "沉醉": "drunk with love", "痴迷": "infatuated", "甜腻": "sickeningly sweet", "蜜糖": "honey", "糖分": "sweetness", // 思念情感 "想念": "missing", "思念": "longing", "牵挂": "caring", "惦记": "thinking of", "念念不忘": "unforgettable", "朝思暮想": "thinking day and night", "魂牵梦绕": "haunting dreams", "日思夜想": "thinking constantly", "相思": "lovesickness", "离愁": "separation sorrow", // 嫉妒情感 "嫉妒": "jealous", "吃醋": "jealous", "争风吃醋": "jealous rivalry", "醋意": "jealousy", "占有欲": "possessiveness", "独占": "monopolize", "不安": "unease", "担心": "worry", "猜疑": "suspicion", // 分合状态 "表白": "confession", "告白": "confession", "求爱": "courtship", "追求": "pursuit", "示爱": "showing love", "求婚": "proposal", "订婚": "engagement", "结婚": "marriage", "蜜月": "honeymoon", "分手": "breakup", "分离": "separation", "离别": "parting", "复合": "reunion", "和好": "reconcile", "重归于好": "getting back together", // 亲密行为 "约会": "dating", "约会": "date", "幽会": "rendezvous", "散步": "walk together", "看电影": "watch movie", "吃饭": "dinner date", "牵手": "holding hands", "拥抱": "hugging", "接吻": "kissing", "依偎": "cuddling", "偎依": "snuggling", "相拥": "embracing", // 情话表达 "情话": "love words", "甜言蜜语": "sweet words", "告白": "confession", "承诺": "promise", "誓言": "vow", "山盟海誓": "eternal vow", "海枯石烂": "until seas dry", "天长地久": "everlasting", "白头偕老": "grow old together", "永结同心": "united forever", // 情感深度 "深爱": "deep love", "挚爱": "cherished love", "痴情": "devoted love", "专情": "faithful love", "深情": "deep affection", "真情": "true feelings", "纯情": "pure love", "真心": "sincere heart", "诚意": "sincerity", "用心": "heartfelt", "全心全意": "wholeheartedly", "一心一意": "single-minded" }, emotional_states: { // 欲望相关 "欲望": "desire", "渴望": "longing", "冲动": "impulse", "饥渴": "thirsty", "急需": "desperate", "迫切": "urgent", "强烈": "intense", "炽热": "burning", "火热": "passionate", "狂野": "wild", "疯狂": "crazy", "失控": "out of control", // 兴奋状态 "兴奋": "excited", "激动": "aroused", "亢奋": "euphoric", "刺激": "stimulation", "快感": "pleasure", "爽": "pleasurable", "舒服": "comfortable", "畅快": "exhilarating", "痛快": "satisfying", "过瘾": "addictive", "上瘾": "addicted", "沉迷": "obsessed", // 满足状态 "满足": "satisfied", "充实": "fulfilled", "完整": "complete", "愉悦": "pleasure", "快乐": "joy", "幸福": "happiness", "陶醉": "intoxicated", "沉醉": "drunk", "迷醉": "enchanted", "销魂": "ecstatic", "飘飘然": "floating", "如痴如醉": "mesmerized", // 紧张焦虑 "紧张": "nervous", "不安": "anxious", "忐忑": "restless", "慌张": "flustered", "手足无措": "at a loss", "局促": "awkward", "窘迫": "embarrassed", "尴尬": "awkward", "难堪": "mortified", "焦虑": "anxious", "担忧": "worried", "忧虑": "concerned", // 期待好奇 "期待": "anticipation", "盼望": "looking forward", "向往": "yearning", "好奇": "curious", "感兴趣": "interested", "想知道": "wondering", "探索": "exploration", "发现": "discovery", "新奇": "novelty", "惊喜": "surprise", "意外": "unexpected", "震撼": "shocking", // 羞耻害羞 "羞耻": "shame", "羞愧": "ashamed", "惭愧": "guilty", "不好意思": "embarrassed", "难为情": "shy", "脸红": "blushing", "害羞": "shy", "腼腆": "bashful", "扭捏": "coy", "矜持": "reserved", "含蓄": "modest", "内敛": "introverted", // 大胆主动 "大胆": "bold", "勇敢": "brave", "无畏": "fearless", "主动": "proactive", "积极": "active", "进取": "aggressive", "直接": "direct", "坦率": "frank", "开放": "open", "放得开": "uninhibited", "豪放": "unrestrained", "奔放": "wild", // 被动顺从 "被动": "passive", "消极": "negative", "退缩": "withdrawn", "顺从": "submissive", "听话": "obedient", "乖巧": "well-behaved", "温顺": "docile", "柔顺": "gentle", "配合": "cooperative", "依赖": "dependent", "依恋": "attached", "粘人": "clingy", // 反抗挣扎 "反抗": "resistant", "抗拒": "resisting", "反对": "opposing", "挣扎": "struggling", "反抗": "rebelling", "违抗": "defying", "拒绝": "refusing", "推辞": "declining", "回避": "avoiding", "逃避": "escaping", "躲避": "hiding", "闪躲": "dodging", // 情感波动 "矛盾": "conflicted", "纠结": "tangled", "复杂": "complicated", "混乱": "confused", "迷茫": "lost", "困惑": "puzzled", "犹豫": "hesitant", "踌躇": "hesitating", "不决": "undecided", "摇摆": "wavering", "动摇": "shaken", "不定": "unstable" } }; let isProcessing = false; let currentProgressButton = null; let processedMessages = new Map(); let currentImageUrl = null; let currentSettings = null; let lastScreenSize = null; function getCurrentScreenSize() { return window.innerWidth <= 1000 ? 'small' : 'large'; } function handleWindowResize() { if (!isActive()) return; const currentScreenSize = getCurrentScreenSize(); if (lastScreenSize && lastScreenSize !== currentScreenSize && currentImageUrl && currentSettings) { $('#wallhaven-app-background, #wallhaven-chat-background').remove(); $('#wallhaven-app-overlay, #wallhaven-chat-overlay').remove(); applyBackgroundToApp(currentImageUrl, currentSettings); } lastScreenSize = currentScreenSize; } function clearBackgroundState() { document.querySelectorAll('[id^="wallhaven-"]').forEach(el => el.remove()); currentImageUrl = null; currentSettings = null; lastScreenSize = null; } function getWallhavenSettings() { if (!extension_settings[EXT_ID].wallhavenBackground) { extension_settings[EXT_ID].wallhavenBackground = structuredClone(defaultSettings); } const settings = extension_settings[EXT_ID].wallhavenBackground; for (const key in defaultSettings) { if (settings[key] === undefined) { settings[key] = defaultSettings[key]; } } return settings; } function isActive() { if (!window.isXiaobaixEnabled) return false; const settings = getWallhavenSettings(); return settings.enabled; } function isLandscapeOrientation() { return window.innerWidth > window.innerHeight; } function getRatiosForOrientation() { if (isLandscapeOrientation()) { return "16x9,16x10,21x9"; } else { return "9x16,10x16,1x1,9x18"; } } function showProgressInMessageHeader(messageElement, text) { const flexContainer = messageElement.querySelector('.flex-container.flex1.alignitemscenter'); if (!flexContainer) return null; removeProgressFromMessageHeader(); const progressButton = document.createElement('div'); progressButton.className = 'mes_btn wallhaven_progress_indicator'; progressButton.style.cssText = ` color: #007acc !important; cursor: default !important; font-size: 11px !important; padding: 2px 6px !important; opacity: 0.9; `; progressButton.innerHTML = `${text}`; progressButton.title = '正在为消息生成配图...'; flexContainer.appendChild(progressButton); currentProgressButton = progressButton; return progressButton; } function updateProgressText(text) { if (currentProgressButton) { currentProgressButton.innerHTML = `${text}`; } } function removeProgressFromMessageHeader() { if (currentProgressButton) { currentProgressButton.remove(); currentProgressButton = null; } document.querySelectorAll('.wallhaven_progress_indicator').forEach(el => el.remove()); } function renderCustomTagsList() { const settings = getWallhavenSettings(); const container = document.getElementById('wallhaven_custom_tags_list'); if (!container) return; container.innerHTML = ''; if (!settings.customTags || settings.customTags.length === 0) { container.innerHTML = '
'; return; } settings.customTags.forEach(tag => { const tagElement = document.createElement('div'); tagElement.className = 'custom-tag-item'; tagElement.innerHTML = ` ${tag} × `; container.appendChild(tagElement); }); container.querySelectorAll('.custom-tag-remove').forEach(btn => { btn.addEventListener('click', function() { removeCustomTag(this.dataset.tag); }); }); } function addCustomTag(tag) { if (!tag || !tag.trim()) return; tag = tag.trim().toLowerCase(); const settings = getWallhavenSettings(); if (!settings.customTags) { settings.customTags = []; } if (settings.customTags.includes(tag)) { return false; } settings.customTags.push(tag); saveSettingsDebounced(); renderCustomTagsList(); return true; } function removeCustomTag(tag) { const settings = getWallhavenSettings(); if (!settings.customTags) return; const index = settings.customTags.indexOf(tag); if (index > -1) { settings.customTags.splice(index, 1); saveSettingsDebounced(); renderCustomTagsList(); } } function extractTagsFromText(text, isBgMode = false) { const settings = getWallhavenSettings(); const customTagObjs = (settings.customTags || []).map(tag => ({ tag: tag, category: 'custom', weight: tagWeights.custom, position: text.lastIndexOf(tag) })); if (isBgMode) { const bgCategories = ['locations', 'weather_time', 'objects']; const tagsByCategory = {}; bgCategories.forEach(category => { tagsByCategory[category] = []; if (wallhavenTags[category]) { Object.entries(wallhavenTags[category]).forEach(([chinese, english]) => { const lastPos = text.lastIndexOf(chinese); if (lastPos !== -1) { tagsByCategory[category].push({ tag: english, category: category, weight: tagWeights[category] || 1, position: lastPos, chinese: chinese }); } }); } }); const selectedTags = [...customTagObjs]; Object.entries(tagsByCategory).forEach(([category, tags]) => { if (tags.length === 0) return; tags.sort((a, b) => b.position - a.position); const selectedFromCategory = tags.slice(0, 1); selectedFromCategory.forEach(tagObj => { selectedTags.push({ tag: tagObj.tag, category: tagObj.category, weight: tagObj.weight }); }); }); if (selectedTags.length === customTagObjs.length) { selectedTags.push({ tag: 'landscape', category: 'background_fallback', weight: 1 }); } return { tags: selectedTags }; } else { const tagsByCategory = {}; Object.keys(wallhavenTags).forEach(category => { tagsByCategory[category] = []; Object.entries(wallhavenTags[category]).forEach(([chinese, english]) => { const lastPos = text.lastIndexOf(chinese); if (lastPos !== -1) { tagsByCategory[category].push({ tag: english, category: category, weight: tagWeights[category] || 1, position: lastPos, chinese: chinese }); } }); }); const selectedTags = [...customTagObjs]; Object.entries(tagsByCategory).forEach(([category, tags]) => { if (tags.length === 0) return; tags.sort((a, b) => b.position - a.position); let maxCount = 1; if (['characters', 'clothing', 'body_features'].includes(category)) { maxCount = 2; } const selectedFromCategory = tags.slice(0, maxCount); selectedFromCategory.forEach(tagObj => { selectedTags.push({ tag: tagObj.tag, category: tagObj.category, weight: tagObj.weight }); }); }); return { tags: selectedTags }; } } async function fetchWithCFWorker(targetUrl) { const cfWorkerUrl = 'https://wallhaven.velure.top/?url='; const finalUrl = cfWorkerUrl + encodeURIComponent(targetUrl); const response = await fetch(finalUrl); if (!response.ok) { throw new Error(`CF Worker请求失败: HTTP ${response.status} - ${response.statusText}`); } return response; } async function searchSingleTag(tagObj, category, purity, isBgMode) { let searchTag = tagObj.tag; if (isBgMode) { searchTag = `${tagObj.tag} -girl -male -people -anime`; } const ratios = getRatiosForOrientation(); const wallhavenUrl = `https://wallhaven.cc/api/v1/search?q=${encodeURIComponent(searchTag)}&categories=${category}&purity=${purity}&ratios=${ratios}&sorting=favorites&page=1&`; try { const response = await fetchWithCFWorker(wallhavenUrl); const data = await response.json(); return { tagObj: tagObj, success: true, total: data.meta.total, images: data.data || [] }; } catch (error) { return { tagObj: tagObj, success: false, error: error.message, total: 0, images: [] }; } } async function intelligentTagMatching(tagObjs, settings) { if (!tagObjs || tagObjs.length === 0) { throw new Error('没有可用的标签'); } const allImages = new Map(); for (let i = 0; i < tagObjs.length; i++) { if (!isActive()) { throw new Error('功能已禁用'); } const tagObj = tagObjs[i]; const isCustom = tagObj.category === 'custom' ? '[自定义]' : ''; updateProgressText(`搜索 ${i + 1}/${tagObjs.length}: ${isCustom}${tagObj.tag} (权重${tagObj.weight})`); const result = await searchSingleTag(tagObj, settings.category, settings.purity, settings.bgMode); if (result.success) { result.images.forEach(img => { if (!allImages.has(img.id)) { allImages.set(img.id, { ...img, matchedTags: [tagObj], weightedScore: tagObj.weight }); } else { const existingImg = allImages.get(img.id); existingImg.matchedTags.push(tagObj); existingImg.weightedScore += tagObj.weight; } }); } if (i < tagObjs.length - 1) { await new Promise(resolve => setTimeout(resolve, 500)); } } const allImagesArray = Array.from(allImages.values()); if (allImagesArray.length === 0) { throw new Error('所有标签都没有找到匹配的图片'); } allImagesArray.sort((a, b) => { if (b.weightedScore !== a.weightedScore) { return b.weightedScore - a.weightedScore; } return b.favorites - a.favorites; }); const maxWeightedScore = allImagesArray[0].weightedScore; const bestMatches = allImagesArray.filter(img => img.weightedScore === maxWeightedScore); const randomIndex = Math.floor(Math.random() * bestMatches.length); return bestMatches[randomIndex]; } function applyMessageStyling() { const mesElements = document.querySelectorAll('#chat .mes:not([data-wallhaven-styled])'); mesElements.forEach(mes => { mes.style.cssText += ` backdrop-filter: none !important; -webkit-backdrop-filter: none !important; background-color: transparent !important; box-shadow: none !important; position: relative !important; z-index: 1002 !important; `; mes.setAttribute('data-wallhaven-styled', 'true'); }); const mesTextElements = document.querySelectorAll('#chat .mes_text:not([data-wallhaven-text-styled])'); mesTextElements.forEach(mesText => { mesText.style.cssText += ` text-shadow: rgba(0, 0, 0, 0.8) 1px 1px 2px !important; color: inherit !important; position: relative !important; z-index: 1003 !important; `; mesText.setAttribute('data-wallhaven-text-styled', 'true'); }); const messageElements = document.querySelectorAll('#chat .mes, #chat .mes_text, #chat .name, #chat .mes_img, #chat .mes_avatar, #chat .mes_btn'); messageElements.forEach(element => { if (element && !element.hasAttribute('data-wallhaven-z-styled')) { element.style.cssText += ` position: relative !important; z-index: 1002 !important; `; element.setAttribute('data-wallhaven-z-styled', 'true'); } }); } function applyBackgroundToApp(imageUrl, settings) { currentImageUrl = imageUrl; currentSettings = { ...settings }; lastScreenSize = getCurrentScreenSize(); const isSmallScreen = window.innerWidth <= 1000; if (isSmallScreen) { const chatElement = document.getElementById('chat'); if (!chatElement) return; const bgId = 'wallhaven-mobile-background'; const overlayId = 'wallhaven-mobile-overlay'; document.querySelectorAll('[id^="wallhaven-"]').forEach(el => el.remove()); let topOffset = 0; const rightNavHolder = document.getElementById('rightNavHolder'); if (rightNavHolder) { const rect = rightNavHolder.getBoundingClientRect(); topOffset = rect.bottom; } else { topOffset = 50; } let backgroundContainer = document.getElementById(bgId); let overlay = document.getElementById(overlayId); if (!backgroundContainer) { backgroundContainer = document.createElement('div'); backgroundContainer.id = bgId; backgroundContainer.style.cssText = ` position: fixed !important; top: ${topOffset}px !important; left: 0 !important; right: 0 !important; bottom: 0 !important; width: 100vw !important; height: calc(100vh - ${topOffset}px) !important; background-size: 100% auto !important; background-position: top center !important; background-repeat: no-repeat !important; z-index: -1 !important; pointer-events: none !important; overflow: hidden !important; `; document.body.appendChild(backgroundContainer); } if (!overlay) { overlay = document.createElement('div'); overlay.id = overlayId; overlay.style.cssText = ` position: fixed !important; top: ${topOffset}px !important; left: 0 !important; right: 0 !important; bottom: 0 !important; width: 100vw !important; height: calc(100vh - ${topOffset}px) !important; background-color: rgba(0, 0, 0, ${settings.opacity}) !important; z-index: 0 !important; pointer-events: none !important; overflow: hidden !important; `; document.body.appendChild(overlay); } backgroundContainer.style.backgroundImage = `url("${imageUrl}")`; overlay.style.backgroundColor = `rgba(0, 0, 0, ${settings.opacity})`; backgroundContainer.style.top = `${topOffset}px`; backgroundContainer.style.height = `calc(100vh - ${topOffset}px)`; overlay.style.top = `${topOffset}px`; overlay.style.height = `calc(100vh - ${topOffset}px)`; if (chatElement) { chatElement.style.cssText += ` background-color: transparent !important; background-image: none !important; background: transparent !important; position: relative !important; z-index: 1 !important; backdrop-filter: none !important; -webkit-backdrop-filter: none !important; `; } applyMessageStyling(); } else { const targetContainer = document.getElementById('expression-wrapper'); if (!targetContainer) return; const bgId = 'wallhaven-app-background'; const overlayId = 'wallhaven-app-overlay'; let backgroundContainer = document.getElementById(bgId); let overlay = document.getElementById(overlayId); if (!backgroundContainer) { backgroundContainer = document.createElement('div'); backgroundContainer.id = bgId; backgroundContainer.style.cssText = ` position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-size: 100% auto; background-position: top center; background-repeat: no-repeat; z-index: 1; pointer-events: none; `; targetContainer.insertBefore(backgroundContainer, targetContainer.firstChild); } if (!overlay) { overlay = document.createElement('div'); overlay.id = overlayId; overlay.style.cssText = ` position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, ${settings.opacity}); z-index: 2; pointer-events: none; `; targetContainer.insertBefore(overlay, targetContainer.firstChild); } backgroundContainer.style.backgroundImage = `url("${imageUrl}")`; overlay.style.backgroundColor = `rgba(0, 0, 0, ${settings.opacity})`; targetContainer.style.position = 'relative'; const chatElement = document.getElementById('chat'); if (chatElement) { chatElement.style.cssText += ` background-color: transparent !important; background-image: none !important; background: transparent !important; position: relative; z-index: 3; backdrop-filter: none !important; -webkit-backdrop-filter: none !important; box-shadow: none !important; border: none !important; text-shadow: none !important; opacity: 1 !important; `; } applyMessageStyling(); } } function isMessageComplete(messageElement) { const regenerateBtn = messageElement.querySelector('.mes_regenerate'); const editBtn = messageElement.querySelector('.mes_edit'); const hasButtons = regenerateBtn || editBtn; const mesText = messageElement.querySelector('.mes_text'); const hasContent = mesText && mesText.textContent.trim().length > 0; const hasStreamingIndicator = messageElement.querySelector('.typing_indicator') || messageElement.querySelector('.mes_loading') || messageElement.classList.contains('streaming'); return hasButtons && hasContent && !hasStreamingIndicator; } function getContentHash(text) { let hash = 0; if (text.length === 0) return hash; for (let i = 0; i < text.length; i++) { const char = text.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; } return hash.toString(); } function shouldProcessMessage(messageId, messageText) { const contentHash = getContentHash(messageText); const storedHash = processedMessages.get(messageId); return !storedHash || storedHash !== contentHash; } function markMessageProcessed(messageId, messageText) { const contentHash = getContentHash(messageText); processedMessages.set(messageId, contentHash); } async function handleAIMessage(data) { if (!isActive() || isProcessing) return; try { isProcessing = true; const messageId = data.messageId || data; if (!messageId) return; const messageElement = document.querySelector(`div.mes[mesid="${messageId}"]`); if (!messageElement || messageElement.classList.contains('is_user')) return; let retryCount = 0; const maxRetries = 10; while (retryCount < maxRetries) { if (isMessageComplete(messageElement)) { break; } retryCount++; await new Promise(resolve => setTimeout(resolve, 1000)); if (!isActive()) return; } const mesText = messageElement.querySelector('.mes_text'); if (!mesText) return; const messageText = mesText.textContent || ''; if (!messageText.trim() || messageText.length < 10) return; if (!shouldProcessMessage(messageId, messageText)) { return; } markMessageProcessed(messageId, messageText); const settings = getWallhavenSettings(); showProgressInMessageHeader(messageElement, '提取标签中...'); const result = extractTagsFromText(messageText, settings.bgMode); if (result.tags.length === 0) { updateProgressText('未提取到标签'); setTimeout(removeProgressFromMessageHeader, 2000); return; } if (!isActive()) return; const orientation = isLandscapeOrientation() ? '横屏' : '竖屏'; const modeText = settings.bgMode ? '背景' : '角色'; const totalWeight = result.tags.reduce((sum, tagObj) => sum + tagObj.weight, 0); const customCount = result.tags.filter(t => t.category === 'custom').length; updateProgressText(`${orientation}${modeText}:提取到 ${result.tags.length} 个标签 (自定义${customCount}个,总权重${totalWeight})`); await new Promise(resolve => setTimeout(resolve, 500)); if (!isActive()) return; const selectedImage = await intelligentTagMatching(result.tags, settings); if (!isActive()) return; updateProgressText('应用背景中...'); const imageUrl = `https://wallhaven.velure.top/?url=${encodeURIComponent(selectedImage.path)}`; applyBackgroundToApp(imageUrl, settings); const coreTagsCount = selectedImage.matchedTags.filter(t => t.weight >= 2).length; const customMatchCount = selectedImage.matchedTags.filter(t => t.category === 'custom').length; updateProgressText(`${modeText}配图完成! 核心匹配${coreTagsCount}个 自定义${customMatchCount}个 权重${selectedImage.weightedScore}`); setTimeout(removeProgressFromMessageHeader, 2000); } catch (error) { updateProgressText(`配图失败: ${error.message.length > 20 ? error.message.substring(0, 20) + '...' : error.message}`); setTimeout(removeProgressFromMessageHeader, 3000); } finally { isProcessing = false; } } function updateSettingsControls() { const settings = getWallhavenSettings(); $('#wallhaven_enabled').prop('checked', settings.enabled); $('#wallhaven_bg_mode').prop('checked', settings.bgMode); $('#wallhaven_category').val(settings.category); $('#wallhaven_purity').val(settings.purity); $('#wallhaven_opacity').val(settings.opacity); $('#wallhaven_opacity_value').text(Math.round(settings.opacity * 100) + '%'); // 控制后续设置的显示/隐藏 const settingsContainer = $('#wallhaven_settings_container'); if (settings.enabled) { settingsContainer.show(); } else { settingsContainer.hide(); } renderCustomTagsList(); } function initSettingsEvents() { $('#wallhaven_enabled').off('change').on('change', function() { if (!window.isXiaobaixEnabled) return; const settings = getWallhavenSettings(); const wasEnabled = settings.enabled; settings.enabled = $(this).prop('checked'); saveSettingsDebounced(); // 控制后续设置的显示/隐藏 const settingsContainer = $('#wallhaven_settings_container'); if (settings.enabled) { settingsContainer.show(); } else { settingsContainer.hide(); } if (settings.enabled && !wasEnabled) { bindMessageHandlers(); } else if (!settings.enabled && wasEnabled) { clearBackgroundState(); removeProgressFromMessageHeader(); processedMessages.clear(); isProcessing = false; unbindMessageHandlers(); } }); $('#wallhaven_bg_mode').off('change').on('change', function() { if (!window.isXiaobaixEnabled) return; const settings = getWallhavenSettings(); settings.bgMode = $(this).prop('checked'); saveSettingsDebounced(); }); $('#wallhaven_category').off('change').on('change', function() { if (!window.isXiaobaixEnabled) return; const settings = getWallhavenSettings(); settings.category = $(this).val(); saveSettingsDebounced(); }); $('#wallhaven_purity').off('change').on('change', function() { if (!window.isXiaobaixEnabled) return; const settings = getWallhavenSettings(); settings.purity = $(this).val(); saveSettingsDebounced(); }); $('#wallhaven_opacity').off('input').on('input', function() { if (!window.isXiaobaixEnabled) return; const settings = getWallhavenSettings(); settings.opacity = parseFloat($(this).val()); $('#wallhaven_opacity_value').text(Math.round(settings.opacity * 100) + '%'); $('#wallhaven-app-overlay, #wallhaven-chat-overlay').css('background-color', `rgba(0, 0, 0, ${settings.opacity})`); saveSettingsDebounced(); }); $('#wallhaven_add_custom_tag').off('click').on('click', function() { if (!window.isXiaobaixEnabled) return; const input = document.getElementById('wallhaven_custom_tag_input'); const tag = input.value.trim(); if (tag) { if (addCustomTag(tag)) { input.value = ''; } else { input.style.borderColor = '#ff6b6b'; setTimeout(() => { input.style.borderColor = ''; }, 1000); } } }); $('#wallhaven_custom_tag_input').off('keypress').on('keypress', function(e) { if (!window.isXiaobaixEnabled) return; if (e.which === 13) { $('#wallhaven_add_custom_tag').click(); } }); } function bindMessageHandlers() { messageEvents.cleanup(); messageEvents.on(event_types.MESSAGE_RECEIVED, handleAIMessage); if (event_types.MESSAGE_SWIPED) { messageEvents.on(event_types.MESSAGE_SWIPED, handleAIMessage); } if (event_types.MESSAGE_EDITED) { messageEvents.on(event_types.MESSAGE_EDITED, handleAIMessage); } if (event_types.MESSAGE_UPDATED) { messageEvents.on(event_types.MESSAGE_UPDATED, handleAIMessage); } } function unbindMessageHandlers() { messageEvents.cleanup(); } function handleGlobalStateChange(event) { const globalEnabled = event.detail.enabled; const wallhavenControls = [ 'wallhaven_enabled', 'wallhaven_bg_mode', 'wallhaven_category', 'wallhaven_purity', 'wallhaven_opacity', 'wallhaven_custom_tag_input', 'wallhaven_add_custom_tag' ]; wallhavenControls.forEach(id => { $(`#${id}`).prop('disabled', !globalEnabled).toggleClass('disabled-control', !globalEnabled); }); if (globalEnabled) { updateSettingsControls(); initSettingsEvents(); if (isActive()) { bindMessageHandlers(); } } else { clearBackgroundState(); removeProgressFromMessageHeader(); processedMessages.clear(); isProcessing = false; unbindMessageHandlers(); $('#wallhaven_enabled, #wallhaven_bg_mode, #wallhaven_category, #wallhaven_purity, #wallhaven_opacity, #wallhaven_add_custom_tag').off(); $('#wallhaven_custom_tag_input').off(); } } function handleChatChanged() { processedMessages.clear(); clearBackgroundState(); removeProgressFromMessageHeader(); isProcessing = false; } function initWallhavenBackground() { const globalEnabled = window.isXiaobaixEnabled !== undefined ? window.isXiaobaixEnabled : true; const wallhavenControls = [ 'wallhaven_enabled', 'wallhaven_bg_mode', 'wallhaven_category', 'wallhaven_purity', 'wallhaven_opacity', 'wallhaven_custom_tag_input', 'wallhaven_add_custom_tag' ]; wallhavenControls.forEach(id => { $(`#${id}`).prop('disabled', !globalEnabled).toggleClass('disabled-control', !globalEnabled); }); if (globalEnabled) { updateSettingsControls(); initSettingsEvents(); if (isActive()) { bindMessageHandlers(); } } document.addEventListener('xiaobaixEnabledChanged', handleGlobalStateChange); globalEvents.on(event_types.CHAT_CHANGED, handleChatChanged); window.addEventListener('resize', handleWindowResize); lastScreenSize = getCurrentScreenSize(); return { cleanup }; } function cleanup() { messageEvents.cleanup(); globalEvents.cleanup(); document.removeEventListener('xiaobaixEnabledChanged', handleGlobalStateChange); window.removeEventListener('resize', handleWindowResize); clearBackgroundState(); removeProgressFromMessageHeader(); isProcessing = false; processedMessages.clear(); currentProgressButton = null; currentImageUrl = null; currentSettings = null; } export { initWallhavenBackground };