// // AICowApi.swift // Crush // // Created by Leon on 2025/8/8. // import Moya let AICowProvider = APIConfig.useMock && AICowAPI.useMock ? MoyaProvider(endpointClosure: myEndpointClosure, stubClosure: { target in let data = target.sampleData if data.count > 0 { return .delayed(seconds: 0.7) } else { return .never } }) : MoyaProvider(requestClosure: myRequestClosure) enum AICowAPI { static let useMock: Bool = true /// 生成任务的通用方法 /** GEN_PROFILE_BY_NON AI一键生成人物基础信息 AI自行创作 GEN_PROFILE_BY_CONTENT AI一键生成人物基础信息 AI根据用户输入进行创作 GEN_DIALOG_STYLE_BY_NON AI一键生成对话风格 AI自行创作 GEN_DIALOG_STYLE_BY_CONTENT AI一键生成对话风格 AI根据用户输入进行创作 GEN_PROLOGUE_BY_NON AI一键生成开场白 AI自行创作 GEN_PROLOGUE_BY_CONTENT AI一键生成开场白 AI根据用户输入进行创作 GEN_INTRODUCTION AI一键生成人物简介 AI总结 IMAGE_REFERENCE_V2 图生文-参考图生成prompt TEXT_TO_IMAGE_PROMPT_V2 文生图-生成6组不同的prompt IMAGE_REFERENCE 图生文-参考图生成prompt TXT_TO_IMAGE_PROMPT 文生图-生成6组不同的prompt */ case aiContentGenerate(params: [String: Any]) // MARK: AI Pics case imageGenerateCreateTask(params: [String: Any]) case imageGeneratedQuery(batchNo: String) // MARK: AI Audio case voiceAICallRtcToken(roomId: String) /// 语音通话操作 case voiceCallOperate(params: [String: Any]) /// 语音转文本 case voiceAsr(voiceBase64: String) /// 语音转文本v2, url:s3 mp3地址 case voiceAsr2(url: String, aiId: Int) /// 生成语音 case voiceTts(params:[String: Any]) // MARK: Chat text suggestions case supChatContent(aiId : Int) /// 删除会话、删除所有消息需要调用此接口 case aiMessageDel(params:[String: Any]) } extension AICowAPI: TargetType { var baseURL: URL { return URL(string: APIConfig.cow)! } var path: String { switch self { case .aiContentGenerate: return "/web/gen/user-content-v1" case .imageGenerateCreateTask: return "/web/gen/image-ct" case .imageGeneratedQuery: return "/web/gen/image-pl" case .voiceAICallRtcToken: return "/web/voice-chat/gen-rtc-tk" case .voiceCallOperate: return "/web/voice-chat/opt" case .voiceAsr: return "/web/voice/asr" case .voiceAsr2: return "/web/voice/asr-v2" case .voiceTts: return "/web/voice/tts-v2" case .supChatContent : return "/web/gen/sup-content-v2" case .aiMessageDel: return "/web/ai-message/del" } } var method: Moya.Method { return .post } var task: Task { var mParams = [String: Any]() switch self { case let .aiContentGenerate(params): mParams = params case let .imageGenerateCreateTask(params): mParams = params case let .imageGeneratedQuery(batchNo): mParams.updateValue(batchNo, forKey: "batchNo") case let .voiceAICallRtcToken(roomId): mParams.updateValue(roomId, forKey: "roomId") case let .voiceCallOperate(params): mParams = params case .voiceAsr(let voiceBase64): mParams.updateValue(voiceBase64, forKey: "data") case .voiceAsr2(let url, let aiId): mParams.updateValue(url, forKey: "url") mParams.updateValue(aiId, forKey: "aiId") case .voiceTts(let params): mParams = params case .supChatContent(let aiId): mParams.updateValue(aiId, forKey: "aiId") case .aiMessageDel(let params): mParams = params } mParams.updateValue("IOS", forKey: "appClient") mParams.updateValue(UIDevice.UUID, forKey: "deviceCode") return .requestParameters(parameters: mParams, encoding: JSONEncoding.default) } var headers: [String: String]? { return APIConfig.apiHeaders() } var sampleData: Data { switch self { case .aiContentGenerate: let content = """ { "content":在某一个平凡的清晨阳光透过薄薄的窗帘洒落在房间里空气中漂浮着淡淡的咖啡香气时钟滴答作响仿佛在提醒着新的一天已经开始世界在悄然运转而人们也在各自的节奏里迎接生活有人匆忙穿过街道去赶上地铁有人推开门迎接清风与日光有人依旧在梦中与自己短暂的安宁相伴而这一切都构成了城市每日的序曲生活的美好并不总是轰轰烈烈它常常隐藏在最琐碎的细节里比如早晨一杯热牛奶的温度比如路口遇见陌生人礼貌的点头比如远方的朋友忽然发来的一句问候让你觉得再孤单的日子也有温暖的痕迹我们习惯把目光投向远方幻想着某一天能抵达一个理想的未来却常常忘了眼前的每一分每一秒才是真正的存在当我们追逐着尚未抵达的目标心里常常会生出焦虑觉得自己不够快不够好不够幸运但如果静下心来仔细看看你会发现其实生命从来没有亏待过任何人它总会在不同的阶段以不同的方式让你体验成长与收获也许是一段艰难的经历让你学会坚强也许是一场意外的遇见让你感到世界柔软也许是一份迟来的鼓励让你重新点燃希望人生从不是一条直线而更像是一条蜿蜒的河流它绕过高山经过峡谷有时奔腾有时平缓而我们要做的不是预测下一个转弯会带来什么而是学会在当下的河水里尽情漂流感受每一段风景带来的独特意义很多时候我们被告知要努力要成功要拥有别人眼中的光鲜亮丽于是拼命向前不敢停歇生怕被落下生怕被否定可真正值得珍惜的却往往是那些慢下来的时刻是与家人坐在一起谈笑风生的晚餐是一个人在书桌前静静读完一本书的午后是走在公园小径上不经意抬头看见的那片湛蓝天空这些微小而真实的片段才是支撑我们走下去的力量幸福不是宏大的目标而是一点一滴的积累正如滴水汇聚成河尘埃凝聚成星无数平凡的瞬间堆叠出生命的厚度很多人说他们害怕孤独害怕失败害怕努力没有回报可是如果换一个角度想想孤独是一种与自己对话的机会失败是一次重塑的契机努力没有回报的过程里也藏着你独有的成长轨迹当我们真正理解这些或许就会少一些抱怨多一些笃定少一些焦虑多一些耐心生命的意义从来不是一个标准答案它更像是一场没有剧本的旅行你无法预知下一个站点会遇见什么也无法控制沿途的天气是否晴朗你能做的只是带着一颗开放的心勇敢走下去接受遇见的一切并在其中找到属于自己的答案而当你慢慢这样生活时你会惊讶地发现世界似乎也在悄然回应你给你更多的惊喜和美好我们每个人都在与时间赛跑却也都在与自己和解从青春的轻狂到中年的稳重再到老年的淡然每一个阶段都有它独特的价值与美丽没有什么是完全的遗憾也没有什么是彻底的圆满人生的意义就在于这种不完美中的坚持与探索当我们终于有一天回头去看那些走过的路会发现原来所谓的结果从来没有那么重要真正让人感动的始终是那些一路陪伴的风景和一路成长的自己所以请不要过于焦虑未来也不要过度执着过去珍惜当下的每一个笑容每一次拥抱每一份努力因为它们才是你生命中最真实的财富人生就像是一首没有句号的诗长短不一起承转合我们无法决定开头和结尾却能决定如何书写中间的篇章而这篇章也终将汇成属于你自己的故事无论是精彩还是平凡都是独一无二的存在当你明白这一点你就会更加从容更加勇敢地走向前方" } """ return .okContent(string: content) // Rt17nP54sd72Hz65Jy34 // dB17Hk54Ww78Of60pj48 // Zr17Tf56yN38Uj92TX81 2025-8-28 机器人 // Em17xx58Cj76KM15ue60 9-25 Lumi // Ct17xT58EJ88AF33Dt73 9-26 我自己 // ok17in58XN88Oe39Io01 动漫风格 // 🔥图名批次 case .imageGenerateCreateTask: let content = """ { "batchNo": "ok17in58XN88Oe39Io01" } """ return .okContent(string: content) // PENDING、COMPLETED // case .imageGeneratedQuery: // let content = """ // [ // { // "status": "COMPLETED", // "imageUrl": "https://hhb.crushlevel.ai/dev/role/17563893218387148.jpg" // }, // { // "status": "FAILED", // "imageUrl": "https://hhb.crushlevel.ai/dev/role/17563893314246930.jpg" // }, // { // "status": "COMPLETED", // "imageUrl": "https://hhb.crushlevel.ai/dev/role/1756389326156188.jpg" // }, // { // "status": "COMPLETED", // "imageUrl": "https://hhb.crushlevel.ai/dev/role/17563893094825005.jpg" // }, // { // "status": "COMPLETED", // "imageUrl": "https://hhb.crushlevel.ai/dev/role/175638931389095.jpg" // }, // { // "status": "COMPLETED", // "imageUrl": "https://hhb.crushlevel.ai/dev/role/17563893179815838.jpg" // } // ] // """ // return .okContent(string: content) // case .voiceAICallRtcToken: // let content = """ // { // "token": "QEWRFQF1234fase" // } // """ // return .okContent(string: content) default: return Data() } } }