讯飞结合kimi辅助文章博客写作

讯飞结合kimi辅助文章写作

引言

我是继上一篇文章之后来写这篇文章的,我写这篇文章的初衷,本意是相当于我们所说的,直接说出来就能转换成文章。

当然,我这边的博客就是用语音转文字,然后进行ai优化来写的.我认为他极大地节省了我们的时间。

接下来我将展示使用方法,若能对大家有所帮助,在历史长河中留下痕迹,我便心满意足。

使用方法

视频描述

我认为演示方法,直接实操最好。我把它放到B站直接开始实操当然这样会比较好.

快捷写博客之语音转文字工具

文字描述

(1)双击77.exe

image-20250707211735265

(2)双击后,脚本将自动使用语音输入。

image-20250707211824680

(3)然后我们开始说话就可以了,说完之后我们可以进行回车。

字体会自动转录,发送给然后直接打出来.

image-20250707211951003

(4)具体来说,我们可以右键点击这个脚本,然后查看输入设置,里面有具体的配置。

image-20250707212026882

(5)所见即所得的后续,我也会持续优化这个脚本,然后再更新日志或发送视频,请大家关注这个专栏。

云盘备份:

https://wwyz.lanzn.com/b00g3eqbuh
密码:ejkj

源代码:

image-20250707211219258

77.ahk

#NoEnv
#SingleInstance Force

; 如果脚本未以管理员权限运行,则重新启动为管理员权限
full_command_line := DllCall("GetCommandLine", "str")
if not (A_IsAdmin or RegExMatch(full_command_line, " /restart(?!\S)"))
{
    try
    {
        if A_IsCompiled
            Run *RunAs "%A_ScriptFullPath%" /restart
        else
            Run *RunAs "%A_AhkPath%" /restart "%A_ScriptFullPath%"
    }
    ExitApp
}

SetWorkingDir %A_ScriptDir%
SendMode Input
SetTitleMatchMode, 2

; 包含 JSON.ahk(请确保 JSON.ahk 文件在脚本目录下或正确路径中)
#Include JSON.ahk

; 全局变量
global MouseX, MouseY, ActiveWin, SettingsHwnd, VoiceHwnd, SendEnterAfterPaste, IsF6Pressed := 0
global PasteTypewriterDelay := 50  ; 编辑器打字机延迟,初始50ms
global EnableXButton2, EnableRightClickLongPress, EnableAutoConfirm
global LastInputTime := 0

; 读取配置文件
IniRead, encryptedApiKey, config.ini, Settings, ApiKey, % ""
IniRead, systemPrompt, config.ini, Settings, SystemPrompt, % "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。"
IniRead, SendEnterAfterPaste, config.ini, Settings, SendEnterAfterPaste, 0
IniRead, AutoStart, config.ini, Settings, AutoStart, 0
IniRead, EnableXButton2, config.ini, Settings, EnableXButton2, 0
IniRead, EnableRightClickLongPress, config.ini, Settings, EnableRightClickLongPress, 0
IniRead, EnableAutoConfirm, config.ini, Settings, EnableAutoConfirm, 0
FileRead, helpText, help.txt

; 简单混淆解密 API 密钥(反转字符串)
api_key := encryptedApiKey ? StrReverse(encryptedApiKey) : "sk-qCyW5PKBWkGvwcn9DZzAHWgF30gzKfS0rPdzRRFUTe1uxuAn"

; 字符串反转函数
StrReverse(str) {
    Loop, Parse, str
        rev := A_LoopField . rev
    return rev
}

; 创建设置 GUI
Gui, Settings: New, +AlwaysOnTop +Resize +MinSize520x540, Kimi AI 助手 - 设置
Gui, Settings: Font, s10, Segoe UI
Gui, Settings: Color, F0F0F0

; Checkboxes
Gui, Settings: Add, Checkbox, vSendEnterAfterPaste x10 y10 w200 h20 gUpdateSendEnter, 粘贴后发送回车
Gui, Settings: Add, Checkbox, vAutoStart x220 y10 w200 h20 gUpdateAutoStart, 开机自启动
Gui, Settings: Add, Checkbox, vEnableXButton2 x10 y40 w200 h20 gUpdateEnableXButton2, 启用 XButton2 确认发送
Gui, Settings: Add, Checkbox, vEnableRightClickLongPress x220 y40 w200 h20 gUpdateEnableRightClickLongPress, 启用右键长按确认发送
Gui, Settings: Add, Checkbox, vEnableAutoConfirm x10 y70 w200 h20 gUpdateEnableAutoConfirm, 启用5秒无输入自动确认

; System prompt
Gui, Settings: Add, Text, x10 y100 w500 h20 +0x200, 种子语句 (系统提示):
Gui, Settings: Add, Edit, vSystemPromptEdit x10 y120 w480 h150 Multi, %systemPrompt%

; Response
Gui, Settings: Add, Text, x10 y280 w500 h20 +0x200, API 返回内容:
Gui, Settings: Add, Edit, vResponse x10 y300 w480 h100 ReadOnly

; Buttons
Gui, Settings: Add, Button, gEditApiKey x10 y410 w80 h30, 编辑密钥
Gui, Settings: Add, Button, gTokenWebsite x100 y410 w80 h30, Token 网站
Gui, Settings: Add, Button, gSaveConfig x190 y410 w80 h30, 保存种子
Gui, Settings: Add, Button, gGetBalance x280 y410 w80 h30, 查询余额
Gui, Settings: Add, Button, gShowHelp x370 y410 w80 h30, 帮助

; Status
Gui, Settings: Add, Text, vStatus x10 y450 w480 h20

; Config file text
Gui, Settings: Add, Text, x10 y480 w480 h20, 配置文件: config.ini (自动保存)

; Typing speed slider
Gui, Settings: Add, Text, x10 y510 w200 h20, 打字速度 (0-100):
Gui, Settings: Add, Slider, vTypingSpeed gUpdateTypingSpeed x220 y510 w200 h20 Range0-100, 5

Gui, Settings: +HwndSettingsHwnd
Gui, Settings: Hide

; 创建语音输入 GUI
Gui, Voice: New, +AlwaysOnTop, Kimi AI 助手 - 语音输入
Gui, Voice: Font, s10, Segoe UI
Gui, Voice: Color, F0F0F0
Gui, Voice: Add, Text, x10 y10 w280 h20 +0x200, 语音输入:
Gui, Voice: Add, Edit, vMyEdit x10 y30 w280 h100 Multi gUpdateLastInputTime
Gui, Voice: Add, Button, gConfirmButton x10 y140 w80 h30, 确定
Gui, Voice: Add, Button, gClearInput x100 y140 w80 h30, 清空
Gui, Voice: +HwndVoiceHwnd
Gui, Voice: Hide

; 设置托盘菜单
Menu, Tray, Add, Show Settings, ShowSettings
Menu, Tray, Add, Exit, ExitApp

; 设置自启动
if (AutoStart) {
    FileCreateShortcut, %A_ScriptFullPath%, %A_Startup%\KimiAI.lnk, %A_ScriptDir%
} else {
    FileDelete, %A_Startup%\KimiAI.lnk
}

; 启动语音转换程序(替换为实际路径)
Run, *RunAs "D:\desk\讯飞测试\3.0.1726\iFlyVoice.exe"
; 定时器检查5秒无输入
SetTimer, CheckAutoConfirm, 1000

return

; XButton1 触发语音输入
F7::
XButton1::
    WinGet, ActiveWin, ID, A
    CoordMode, Mouse, Screen
    MouseGetPos, MouseX, MouseY
    GuiControl, Voice:, MyEdit,
    Gui, Voice: Show, w300 h150
    GuiControl, Voice: Focus, MyEdit
    Sleep, 100  ; 确保窗口激活
    Send {F6 down}
    IsF6Pressed := 1
    LastInputTime := A_TickCount  ; 重置最后输入时间
return

; XButton2 确认发送(如果启用)
~XButton2::
    if (EnableXButton2 && WinActive("ahk_id " VoiceHwnd))
    {
        Gosub, ConfirmButton
    }
return

; 右键长按300毫秒确认发送(如果启用)
~RButton::
    if (EnableRightClickLongPress && WinActive("ahk_id " VoiceHwnd))
    {
        KeyWait, RButton, T0.3
        if (ErrorLevel)
        {
            Gosub, ConfirmButton
        }
    }
return

; Ctrl+Enter 在编辑控件中换行
^Enter::
    IfWinActive, ahk_id %VoiceHwnd%
        Send {Enter}
return

; Enter 松开 F6 并触发确认
$Enter::
    IfWinActive, ahk_id %VoiceHwnd%
    {
        if (IsF6Pressed)
        {
            Send {F6 up}
            IsF6Pressed := 0
            Sleep, 1000  ; 优化为1秒
        }
        Gosub, ConfirmButton
    }
    else
        Send {Enter}
return

; 显示设置窗口
ShowSettings:
    Gui, Settings: Show, w520 h540
return

; 更新发送回车选项
UpdateSendEnter:
    Gui, Settings: Submit, NoHide
    IniWrite, %SendEnterAfterPaste%, config.ini, Settings, SendEnterAfterPaste
    GuiControl, Settings:, Status, 发送回车选项已更新
return

; 更新自启动选项
UpdateAutoStart:
    Gui, Settings: Submit, NoHide
    IniWrite, %AutoStart%, config.ini, Settings, AutoStart
    if (AutoStart) {
        FileCreateShortcut, %A_ScriptFullPath%, %A_Startup%\KimiAI.lnk, %A_ScriptDir%
    } else {
        FileDelete, %A_Startup%\KimiAI.lnk
    }
    GuiControl, Settings:, Status, 自启动选项已更新
return

; 更新 XButton2 选项
UpdateEnableXButton2:
    Gui, Settings: Submit, NoHide
    IniWrite, %EnableXButton2%, config.ini, Settings, EnableXButton2
    GuiControl, Settings:, Status, XButton2 选项已更新
return

; 更新右键长按选项
UpdateEnableRightClickLongPress:
    Gui, Settings: Submit, NoHide
    IniWrite, %EnableRightClickLongPress%, config.ini, Settings, EnableRightClickLongPress
    GuiControl, Settings:, Status, 右键长按选项已更新
return

; 更新自动确认选项
UpdateEnableAutoConfirm:
    Gui, Settings: Submit, NoHide
    IniWrite, %EnableAutoConfirm%, config.ini, Settings, EnableAutoConfirm
    GuiControl, Settings:, Status, 自动确认选项已更新
return

; 更新打字速度
UpdateTypingSpeed:
    Gui, Settings: Submit, NoHide
    PasteTypewriterDelay := Round((TypingSpeed / 100) * 1000)
    GuiControl, Settings:, Status, 打字速度已更新: %TypingSpeed% (延迟: %PasteTypewriterDelay%ms)
return

; 确认按钮
ConfirmButton:
    Gui, Voice: Submit, NoHide
    if (MyEdit = "")
    {
        GuiControl, Settings:, Status, 请输入句子!
        return
    }

    ; 自动保存语音输入
    global tempInput  ; 确保 tempInput 是全局变量
    tempInput := MyEdit

    GuiControl, Settings:, Status, 加载中...

    GuiControlGet, systemPrompt,, SystemPromptEdit
    ; 优化消息结构
    body := "{""model"": ""moonshot-v1-8k"", ""messages"": [{""role"": ""system"", ""content"": """ . systemPrompt . """},{""role"": ""user"", ""content"": """ . MyEdit . """}]}"

    ; 估算 token 数量
    http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
    http.Open("POST", "https://api.moonshot.cn/v1/tokenizers/estimate-token-count", false)
    http.SetRequestHeader("Authorization", "Bearer " . api_key)
    http.SetRequestHeader("Content-Type", "application/json")
    http.Send(body)
    status := http.Status
    tokenResponse := http.ResponseText
    tokenCount := (status = 200 && JSON.Load(tokenResponse).data.total_tokens) ? JSON.Load(tokenResponse).data.total_tokens : ""

    ; 检查令牌计数
    if (tokenCount > 7000)
    {
        GuiControl, Settings:, Status, 警告: token 数 %tokenCount% 可能过高
    }

    ; 获取 AI 回答
    http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
    http.Open("POST", "https://api.moonshot.cn/v1/chat/completions", false)
    http.SetRequestHeader("Authorization", "Bearer " . api_key)
    http.SetRequestHeader("Content-Type", "application/json")
    http.Send(body)
    status := http.Status
    response := http.ResponseText

    if (status = 200)
    {
        obj := JSON.Load(response)
        if (obj.choices && obj.choices.Length() > 0)
        {
            answer := obj.choices[1].message.content
            if (answer = "")
            {
                GuiControl, Settings:, Response, 消息 token 总数: %tokenCount%`n[AI 回答为空]
                GuiControl, Settings:, Status, 请求成功,但 AI 回答为空
            }
            else
            {
                GuiControl, Settings:, Response, % "消息 token 总数: " tokenCount "`nAI 回答: " answer
                GuiControl, Settings:, Status, 请求成功
                
                WinActivate, ahk_id %ActiveWin%
                CoordMode, Mouse, Screen
                MouseMove, %MouseX%, %MouseY%, 0
                for index, char in StrSplit(answer)
                {
                    if (GetKeyState("Esc", "P"))
                        break
                    Send, %char%
                    Sleep, %PasteTypewriterDelay%
                }
                if (SendEnterAfterPaste)
                    Send {Enter}
            }
        }
        else
        {
            GuiControl, Settings:, Response, 消息 token 总数: %tokenCount%`n[无有效 AI 回答]
            GuiControl, Settings:, Status, 错误: API 返回无有效选择
        }
        tempInput := ""  ; 请求成功,清除临时备份
    }
    else
    {
        obj := JSON.Load(response)
        if (obj.error && obj.error.message)
            errorMsg := obj.error.message
        else
            errorMsg := response
        GuiControl, Settings:, Response, 消息 token 总数: %tokenCount%`n[请求失败]`n错误信息: %errorMsg%
        GuiControl, Settings:, Status, 错误: HTTP 状态 %status%
        
        ; 请求失败,询问是否重试
        MsgBox, 4, 请求失败, API 请求失败,是否重试?
        IfMsgBox, Yes
        {
            MyEdit := tempInput  ; 恢复保存的输入
            Gosub, ConfirmButton  ; 重试
        }
        else
        {
            tempInput := ""  ; 清除临时备份
        }
    }

    GuiControl, Voice:, MyEdit,
    Gui, Voice: Hide
return

; 清空输入
ClearInput:
    GuiControl, Voice:, MyEdit,
    GuiControl, Settings:, Status, 输入已清空
return

; 编辑 API 密钥
EditApiKey:
    InputBox, newApiKey, 编辑 API 密钥, 请输入新的 API 密钥 (明文输入),, 300, 150
    if (!ErrorLevel)
    {
        encrypted := StrReverse(newApiKey)
        IniWrite, %encrypted%, config.ini, Settings, ApiKey
        api_key := newApiKey
        GuiControl, Settings:, Status, 密钥更新成功
    }
return

; Token 网站
TokenWebsite:
    Run, https://platform.moonshot.cn/console/api-keys
return

; 保存配置
SaveConfig:
    GuiControlGet, newPrompt,, SystemPromptEdit
    if (newPrompt != "")
    {
        IniWrite, %newPrompt%, config.ini, Settings, SystemPrompt
        systemPrompt := newPrompt
        GuiControl, Settings:, Status, 种子语句更新成功
    }
    else
    {
        GuiControl, Settings:, Status, 种子语句不能为空!
    }
return

; 查询余额
GetBalance:
    GuiControl, Settings:, Status, 加载中...
    http := ComObjCreate("WinHttp.WinHttpRequest.5.1")
    http.Open("GET", "https://api.moonshot.cn/v1/users/me/balance", false)
    http.SetRequestHeader("Authorization", "Bearer " . api_key)
    http.Send()
    status := http.Status
    response := http.ResponseText
    if (status = 200)
    {
        obj := JSON.Load(response)
        if (obj.data && obj.data.available_balance != "")
        {
            available := obj.data.available_balance
            voucher := obj.data.voucher_balance
            cash := obj.data.cash_balance
            GuiControl, Settings:, Response, 可用余额: %available% CNY`n代金券余额: %voucher% CNY`n现金余额: %cash% CNY
            GuiControl, Settings:, Status, 查询成功
        }
        else
        {
            GuiControl, Settings:, Response, [无有效余额数据]
            GuiControl, Settings:, Status, 错误: API 返回无有效余额数据
        }
    }
    else
    {
        GuiControl, Settings:, Response, [请求失败]
        GuiControl, Settings:, Status, 错误: HTTP 状态 %status%
    }
return

; 显示帮助
ShowHelp:
    MsgBox, 0, 使用说明, %helpText%
return

; 更新最后输入时间
UpdateLastInputTime:
    LastInputTime := A_TickCount
return

; 检查5秒无输入自动确认
CheckAutoConfirm:
    if (EnableAutoConfirm && WinActive("ahk_id " VoiceHwnd))
    {
        if (A_TickCount - LastInputTime > 5000)
        {
            Gosub, ConfirmButton
        }
    }
return

GuiClose:
GuiEscape:
    Gui, Settings: Hide
    Gui, Voice: Hide
return

ExitApp:
    ExitApp
return

JSON.ahk

/**
 * Lib: JSON.ahk
 *     JSON lib for AutoHotkey.
 * Version:
 *     v2.1.3 [updated 04/18/2016 (MM/DD/YYYY)]
 * License:
 *     WTFPL [http://wtfpl.net/]
 * Requirements:
 *     Latest version of AutoHotkey (v1.1+ or v2.0-a+)
 * Installation:
 *     Use #Include JSON.ahk or copy into a function library folder and then
 *     use #Include <JSON>
 * Links:
 *     GitHub:     - https://github.com/cocobelgica/AutoHotkey-JSON
 *     Forum Topic - http://goo.gl/r0zI8t
 *     Email:      - cocobelgica <at> gmail <dot> com
 */


/**
 * Class: JSON
 *     The JSON object contains methods for parsing JSON and converting values
 *     to JSON. Callable - NO; Instantiable - YES; Subclassable - YES;
 *     Nestable(via #Include) - NO.
 * Methods:
 *     Load() - see relevant documentation before method definition header
 *     Dump() - see relevant documentation before method definition header
 */
class JSON
{
	/**
	 * Method: Load
	 *     Parses a JSON string into an AHK value
	 * Syntax:
	 *     value := JSON.Load( text [, reviver ] )
	 * Parameter(s):
	 *     value      [retval] - parsed value
	 *     text    [in, ByRef] - JSON formatted string
	 *     reviver   [in, opt] - function object, similar to JavaScript's
	 *                           JSON.parse() 'reviver' parameter
	 */
	class Load extends JSON.Functor
	{
		Call(self, ByRef text, reviver:="")
		{
			this.rev := IsObject(reviver) ? reviver : false
		; Object keys(and array indices) are temporarily stored in arrays so that
		; we can enumerate them in the order they appear in the document/text instead
		; of alphabetically. Skip if no reviver function is specified.
			this.keys := this.rev ? {} : false

			static quot := Chr(34), bashq := "\" . quot
			     , json_value := quot . "{[01234567890-tfn"
			     , json_value_or_array_closing := quot . "{[]01234567890-tfn"
			     , object_key_or_object_closing := quot . "}"

			key := ""
			is_key := false
			root := {}
			stack := [root]
			next := json_value
			pos := 0

			while ((ch := SubStr(text, ++pos, 1)) != "") {
				if InStr(" `t`r`n", ch)
					continue
				if !InStr(next, ch, 1)
					this.ParseError(next, text, pos)

				holder := stack[1]
				is_array := holder.IsArray

				if InStr(",:", ch) {
					next := (is_key := !is_array && ch == ",") ? quot : json_value

				} else if InStr("}]", ch) {
					ObjRemoveAt(stack, 1)
					next := stack[1]==root ? "" : stack[1].IsArray ? ",]" : ",}"

				} else {
					if InStr("{[", ch) {
					; Check if Array() is overridden and if its return value has
					; the 'IsArray' property. If so, Array() will be called normally,
					; otherwise, use a custom base object for arrays
						static json_array := Func("Array").IsBuiltIn || ![].IsArray ? {IsArray: true} : 0
					
					; sacrifice readability for minor(actually negligible) performance gain
						(ch == "{")
							? ( is_key := true
							  , value := {}
							  , next := object_key_or_object_closing )
						; ch == "["
							: ( value := json_array ? new json_array : []
							  , next := json_value_or_array_closing )
						
						ObjInsertAt(stack, 1, value)

						if (this.keys)
							this.keys[value] := []
					
					} else {
						if (ch == quot) {
							i := pos
							while (i := InStr(text, quot,, i+1)) {
								value := StrReplace(SubStr(text, pos+1, i-pos-1), "\\", "\u005c")

								static tail := A_AhkVersion<"2" ? 0 : -1
								if (SubStr(value, tail) != "\")
									break
							}

							if (!i)
								this.ParseError("'", text, pos)

							  value := StrReplace(value,  "\/",  "/")
							, value := StrReplace(value, bashq, quot)
							, value := StrReplace(value,  "\b", "`b")
							, value := StrReplace(value,  "\f", "`f")
							, value := StrReplace(value,  "\n", "`n")
							, value := StrReplace(value,  "\r", "`r")
							, value := StrReplace(value,  "\t", "`t")

							pos := i ; update pos
							
							i := 0
							while (i := InStr(value, "\",, i+1)) {
								if !(SubStr(value, i+1, 1) == "u")
									this.ParseError("\", text, pos - StrLen(SubStr(value, i+1)))

								uffff := Abs("0x" . SubStr(value, i+2, 4))
								if (A_IsUnicode || uffff < 0x100)
									value := SubStr(value, 1, i-1) . Chr(uffff) . SubStr(value, i+6)
							}

							if (is_key) {
								key := value, next := ":"
								continue
							}
						
						} else {
							value := SubStr(text, pos, i := RegExMatch(text, "[\]\},\s]|$",, pos)-pos)

							static number := "number", integer :="integer"
							if value is %number%
							{
								if value is %integer%
									value += 0
							}
							else if (value == "true" || value == "false")
								value := %value% + 0
							else if (value == "null")
								value := ""
							else
							; we can do more here to pinpoint the actual culprit
							; but that's just too much extra work.
								this.ParseError(next, text, pos, i)

							pos += i-1
						}

						next := holder==root ? "" : is_array ? ",]" : ",}"
					} ; If InStr("{[", ch) { ... } else

					is_array? key := ObjPush(holder, value) : holder[key] := value

					if (this.keys && this.keys.HasKey(holder))
						this.keys[holder].Push(key)
				}
			
			} ; while ( ... )

			return this.rev ? this.Walk(root, "") : root[""]
		}

		ParseError(expect, ByRef text, pos, len:=1)
		{
			static quot := Chr(34), qurly := quot . "}"
			
			line := StrSplit(SubStr(text, 1, pos), "`n", "`r").Length()
			col := pos - InStr(text, "`n",, -(StrLen(text)-pos+1))
			msg := Format("{1}`n`nLine:`t{2}`nCol:`t{3}`nChar:`t{4}"
			,     (expect == "")     ? "Extra data"
			    : (expect == "'")    ? "Unterminated string starting at"
			    : (expect == "\")    ? "Invalid \escape"
			    : (expect == ":")    ? "Expecting ':' delimiter"
			    : (expect == quot)   ? "Expecting object key enclosed in double quotes"
			    : (expect == qurly)  ? "Expecting object key enclosed in double quotes or object closing '}'"
			    : (expect == ",}")   ? "Expecting ',' delimiter or object closing '}'"
			    : (expect == ",]")   ? "Expecting ',' delimiter or array closing ']'"
			    : InStr(expect, "]") ? "Expecting JSON value or array closing ']'"
			    :                      "Expecting JSON value(string, number, true, false, null, object or array)"
			, line, col, pos)

			static offset := A_AhkVersion<"2" ? -3 : -4
			throw Exception(msg, offset, SubStr(text, pos, len))
		}

		Walk(holder, key)
		{
			value := holder[key]
			if IsObject(value) {
				for i, k in this.keys[value] {
					; check if ObjHasKey(value, k) ??
					v := this.Walk(value, k)
					if (v != JSON.Undefined)
						value[k] := v
					else
						ObjDelete(value, k)
				}
			}
			
			return this.rev.Call(holder, key, value)
		}
	}

	/**
	 * Method: Dump
	 *     Converts an AHK value into a JSON string
	 * Syntax:
	 *     str := JSON.Dump( value [, replacer, space ] )
	 * Parameter(s):
	 *     str        [retval] - JSON representation of an AHK value
	 *     value          [in] - any value(object, string, number)
	 *     replacer  [in, opt] - function object, similar to JavaScript's
	 *                           JSON.stringify() 'replacer' parameter
	 *     space     [in, opt] - similar to JavaScript's JSON.stringify()
	 *                           'space' parameter
	 */
	class Dump extends JSON.Functor
	{
		Call(self, value, replacer:="", space:="")
		{
			this.rep := IsObject(replacer) ? replacer : ""

			this.gap := ""
			if (space) {
				static integer := "integer"
				if space is %integer%
					Loop, % ((n := Abs(space))>10 ? 10 : n)
						this.gap .= " "
				else
					this.gap := SubStr(space, 1, 10)

				this.indent := "`n"
			}

			return this.Str({"": value}, "")
		}

		Str(holder, key)
		{
			value := holder[key]

			if (this.rep)
				value := this.rep.Call(holder, key, ObjHasKey(holder, key) ? value : JSON.Undefined)

			if IsObject(value) {
			; Check object type, skip serialization for other object types such as
			; ComObject, Func, BoundFunc, FileObject, RegExMatchObject, Property, etc.
				static type := A_AhkVersion<"2" ? "" : Func("Type")
				if (type ? type.Call(value) == "Object" : ObjGetCapacity(value) != "") {
					if (this.gap) {
						stepback := this.indent
						this.indent .= this.gap
					}

					is_array := value.IsArray
				; Array() is not overridden, rollback to old method of
				; identifying array-like objects. Due to the use of a for-loop
				; sparse arrays such as '[1,,3]' are detected as objects({}). 
					if (!is_array) {
						for i in value
							is_array := i == A_Index
						until !is_array
					}

					str := ""
					if (is_array) {
						Loop, % value.Length() {
							if (this.gap)
								str .= this.indent
							
							v := this.Str(value, A_Index)
							str .= (v != "") ? v . "," : "null,"
						}
					} else {
						colon := this.gap ? ": " : ":"
						for k in value {
							v := this.Str(value, k)
							if (v != "") {
								if (this.gap)
									str .= this.indent

								str .= this.Quote(k) . colon . v . ","
							}
						}
					}

					if (str != "") {
						str := RTrim(str, ",")
						if (this.gap)
							str .= stepback
					}

					if (this.gap)
						this.indent := stepback

					return is_array ? "[" . str . "]" : "{" . str . "}"
				}
			
			} else ; is_number ? value : "value"
				return ObjGetCapacity([value], 1)=="" ? value : this.Quote(value)
		}

		Quote(string)
		{
			static quot := Chr(34), bashq := "\" . quot

			if (string != "") {
				  string := StrReplace(string,  "\",  "\\")
				; , string := StrReplace(string,  "/",  "\/") ; optional in ECMAScript
				, string := StrReplace(string, quot, bashq)
				, string := StrReplace(string, "`b",  "\b")
				, string := StrReplace(string, "`f",  "\f")
				, string := StrReplace(string, "`n",  "\n")
				, string := StrReplace(string, "`r",  "\r")
				, string := StrReplace(string, "`t",  "\t")

				static rx_escapable := A_AhkVersion<"2" ? "O)[^\x20-\x7e]" : "[^\x20-\x7e]"
				while RegExMatch(string, rx_escapable, m)
					string := StrReplace(string, m.Value, Format("\u{1:04x}", Ord(m.Value)))
			}

			return quot . string . quot
		}
	}

	/**
	 * Property: Undefined
	 *     Proxy for 'undefined' type
	 * Syntax:
	 *     undefined := JSON.Undefined
	 * Remarks:
	 *     For use with reviver and replacer functions since AutoHotkey does not
	 *     have an 'undefined' type. Returning blank("") or 0 won't work since these
	 *     can't be distnguished from actual JSON values. This leaves us with objects.
	 *     Replacer() - the caller may return a non-serializable AHK objects such as
	 *     ComObject, Func, BoundFunc, FileObject, RegExMatchObject, and Property to
	 *     mimic the behavior of returning 'undefined' in JavaScript but for the sake
	 *     of code readability and convenience, it's better to do 'return JSON.Undefined'.
	 *     Internally, the property returns a ComObject with the variant type of VT_EMPTY.
	 */
	Undefined[]
	{
		get {
			static empty := {}, vt_empty := ComObject(0, &empty, 1)
			return vt_empty
		}
	}

	class Functor
	{
		__Call(method, ByRef arg, args*)
		{
		; When casting to Call(), use a new instance of the "function object"
		; so as to avoid directly storing the properties(used across sub-methods)
		; into the "function object" itself.
			if IsObject(method)
				return (new this).Call(method, arg, args*)
			else if (method == "")
				return (new this).Call(arg, args*)
		}
	}
}

语音转换种子语句:

我下面要给你一段语音转文字的语句, 请你帮我处理这段话, 你输出的时候, 不要多说任何的话, 直接按照我的要求, 给我处理后的话就行了, 其他不要多说, 去掉语气词, 修改错别字, 审视语境中的名词, 不符合原意, 推测, 并修改, 直接给我, 保持原话的风格, 下面是我要处理的话:

致谢

知乎博主:科技鸢

提供讯飞独立脚本, 以供研究

image-20250707211551106

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值