Drafty-基于JSON的标记语言来描述聊天内容

Drafty: 一种富文本格式 (翻译)

这份文档介绍了 Drafty,一种由 Tinode 使用的文本格式,用于为消息添加样式。Drafty 的目标是在表达能力足够的同时,不会开放太多的可能性以避免安全问题。你可以将它视为将 JSON 封装了一下的 markdown。Drafty 受到了 Facebook 的 draft.js 规范的影响。截至撰写本文时,已经存在 JavaScript、Java 和 Swift 的实现。还有一个 Go 实现,可以将 Drafty 转换为纯文本和预览。

这样的好处就是在机器人交互时候可以发送一些格式化的文本,而不仅仅是微信和QQ那种无格式文本;

示例

this is bold, code and italic, strike

combined bold and italic

an url: https://www.example.com/abc#fragment and another https://web.tinode.co

this is a @mention and a #hashtag in a string

second #hashtag

上面的格式可以用下面的方式描述:

{"txt":  "this is bold, code and italic, strike combined bold and italic an url: https://www.example.com/abc#fragment and another www.tinode.co this is a @mention and a #hashtag in a string second #hashtag","fmt": [{ "at":8, "len":4,"tp":"ST" },{ "at":14, "len":4, "tp":"CO" },{ "at":23, "len":6, "tp":"EM"},{ "at":31, "len":6, "tp":"DL" },{ "tp":"BR", "len":1, "at":37 },{ "at":56, "len":6, "tp":"EM" },{ "at":47, "len":15, "tp":"ST" },{ "tp":"BR", "len":1, "at":62 },{ "at":120, "len":13, "tp":"EM" },{ "at":71, "len":36, "key":0 },{ "at":120, "len":13, "key":1 },{ "tp":"BR", "len":1, "at":133 },{ "at":144, "len":8, "key":2 },{ "at":159, "len":8, "key":3 },{ "tp":"BR", "len":1, "at":179 },{ "at":187, "len":8, "key":3 },{ "tp":"BR", "len":1, "at":195 }],"ent": [{ "tp":"LN", "data":{ "url":"https://www.example.com/abc#fragment" } },{ "tp":"LN", "data":{ "url":"http://www.tinode.co" } },{ "tp":"MN", "data":{ "val":"mention" } },{ "tp":"HT", "data":{ "val":"hashtag" } }]
}

结构

Drafty 对象有三个字段:纯文本 txt、行内标记 fmt 和实体 ent

  • 纯文本:消息被转换为纯 Unicode 文本,并且去除了所有标记,保存在 txt 字段中。

  • 行内标记 fmt:行内标记是一个包含了每种样式的数组。每种样式由一个对象表示,至少包含 atlen 字段。at 表示在 txt 中的偏移量,len 是要应用样式的字符数。

    样式的第三个值可以是 tpkey。如果是 tp,则表示样式是基本的文本装饰;如果是 key,则是对 ent 数组的索引,其中包含了更多的样式参数,比如图片或 URL。

  • 实体 ent:实体是一种需要额外数据的文本装饰,例如链接、提及或者标签等。实体由一个包含了两个字段的对象表示,tp 表示实体的类型,data 是类型相关的样式信息。

纯文本

解释在 Drafty 中如何处理纯文本消息。

消息被发送时会被转换成纯 Unicode 文本,并且所有的标记都会被剥离掉,然后保存在 txt 字段中。通常情况下,一个有效的 Drafty 消息可能只包含 txt 字段,即纯文本内容。这意味着如果消息不需要任何样式或实体,那么只需要填充 txt 字段即可。

内联格式 fmt

这段说明了在 Drafty 中的行内格式化样式。具体来说:

  • 行内格式化 是一个包含了各种样式的数组,存储在 fmt 字段中。每种样式都由一个对象表示,至少包含 atlen 字段。at 表示相对于 txt 的偏移量(从 0 开始),len 表示要应用样式的字符数。每种样式的第三个值可能是 tpkey

  • 如果提供了 tp,则表示样式是基本的文本装饰,可以是以下值之一:

    • BR:换行。
    • CO:代码或等宽字体文本,可能带有不同的背景色。
    • DL:删除或删除线文本。
    • EM:强调文本,通常表示为斜体。
    • FM:表单/字段集合;也可以表示为实体。
    • HD:隐藏内容。
    • HL:高亮文本,例如不同颜色或背景的文本;颜色不能指定。
    • RW:格式的逻辑分组,一行;也可以表示为实体。
    • ST:粗体文本。
  • 如果提供了 key,则是一个基于 ent 数组的从 0 开始的索引,其中包含了扩展样式参数,例如图片或 URL。可能的键值包括:

    • AU:嵌入式音频。
    • BN:交互式按钮。
    • EX:通用附件。
    • FM:表单/字段集合;也可以表示为基本装饰。
    • HT:标签,例如 #hashtag。
    • IM:内联图像。
    • LN:链接(URL)https://api.tinode.co。
    • MN:提及,例如 @tinode。
    • RW:格式的逻辑分组,一行;也可以表示为基本装饰。
    • VC:视频(和音频)通话。
    • VD:内联视频。

示例:

解释如何使用 Drafty 中的样式对象。具体来说:

  • { "at":8, "len":4, "tp":"ST"}:表示从 txt 中的偏移量 8 处开始的 4 个字符应用粗体样式 (ST)。
  • { "at":144, "len":8, "key":2 }:表示将实体 ent[2] 插入到位置 144 处,该实体跨越 8 个字符。
  • { "at":-1, "len":0, "key":4 }:表示将实体 ent[4] 显示为文件附件,但不对文本应用任何样式。

这些示例中的样式对象可以缺少 atkeylen 值,客户端应该能够处理这些缺失的情况。如果缺少这些值,则默认将它们视为 0

需要注意的是,atlen 的索引是以 Unicode 代码点 衡量的,而不是字节或字符。目前对于包含 Fitzpatrick 皮肤色调修饰符、变体选择器或与 ZWJ 组合的多代码点字符(例如表情符号)的行为是未定义的。

FM: 表单、订单以及一组输入

表单可以提供对一组元素进行图形化的展示.

是否同意?
{"txt": "是否同意? 是,否","fmt": [{"len": 20, "tp": "FM"}, // missing 'at' is zero: "at": 0{"len": 13, "tp": "ST"}{"at": 13, "len": 1, "tp": "BR"},{"at": 14, "len": 3}, // missing 'key' is zero: "key": 0{"at": 17, "len": 1, "tp": "BR"},{"at": 18, "len": 2, "key": 1},],"ent": [{"tp": "BN", "data": {"name": "yes", "act": "pub", "val": "是!"}},{"tp": "BN", "data": {"name": "no", "act": "pub"}}]
}

如果点击了按钮 , 客户端应该向对方(群组)发送如下的信息:

{"txt": "Yes","fmt": [{"at":-1}],"ent": [{"tp": "EX","data": {"mime": "application/json","val": {"seq": 15, // seq id of the message containing the form."resp": {"yes": "oh yes!"}}}}]
}

The form may be optionally represented as an entity:

{"tp": "FM","data": {"su": true}
}

data.su 描述了交互式表单元素在点击后的行为方式。当 "su": true 时,表示表单是 single use 的:即表单在第一次交互后应更改,以显示它不再接受输入。

这意味着一旦用户与表单交互,表单将被禁用或隐藏,以表示它已经被使用过,不再接受进一步的输入。通常,这是用于在用户提交表单后,防止用户再次进行相同的操作。

实体嵌入 ent

一般来说,实体是一种需要额外(可能很大)数据的文本装饰。一个实体由两个字段组成:tp 表示实体的类型,data 是依赖于类型的样式信息。未知的字段会被忽略。

这意味着在 Drafty 中,实体可以是多种类型的装饰,例如链接、提及、附件等,并且每种类型都有其自己的样式和数据。当客户端解析 Drafty 消息时,它会根据 tp 字段识别实体的类型,并根据该类型的样式信息对文本进行相应的装饰。

AU: 嵌入音频

AU 是一个音频。 data 包括下面的字段:

{"tp": "AU","data": {"mime": "audio/aac","val": "Rt53jUU...iVBORw0KGgoA==","ref": "/v0/file/s/e769gvt1ILE.m4v","preview": "Aw4JKBkAAAAKMSM...vHxgcJhsgESAY""duration": 180000,"name": "ding_dong.m4a","size": 595496}
}
  • ``mime`: 数据格式,例如 ‘audio/ogg’,指定音频文件的 MIME 类型。
  • val: 可选的内联音频数据,以 base64 编码形式提供。这是音频文件的实际数据。
  • ref: 可选的外部音频引用,可以是音频文件的 URL 或文件路径。valref 两者之一必须存在,但不能同时存在。
  • preview: 预览图像的 base64 编码数组,用于生成视觉预览。每个字节代表一个振幅条。
  • duration: 音频记录的持续时间,以毫秒为单位。
  • name: 原始文件的可选名称。
  • size: 文件的可选大小,以字节为单位。

这些字段描述了音频实体的各个方面,例如其数据、类型、持续时间、大小等。这些信息可以用于在客户端显示音频消息,并提供相应的控制和交互功能。

要创建一个仅包含单个音频记录而没有文本的消息,可以使用以下 Drafty 格式:

{"txt": " ","fmt": [{ "len": 1 }],"ent": [{"tp": "AU","data": {"mime": "audio/aac","val": "Rt53jUU...iVBORw0KGgoA==","ref": "/v0/file/s/e769gvt1ILE.m4v","preview": "Aw4JKBkAAAAKMSM...vHxgcJhsgESAY","duration": 180000,"name": "ding_dong.m4a","size": 595496}}]
}

重要的安全注意事项:valref 字段可能包含恶意负载。客户端应该限制 ref 字段中的 URL 方案仅限于 httphttps。客户端应该只有在将 val 字段正确转换为音频后才向用户展示其内容。

这意味着客户端在处理音频实体时应该采取必要的安全措施来防止恶意行为。在处理 ref 字段时,客户端应该验证 URL 的方案,确保它是安全的,防止恶意链接导致的安全问题。同时,在使用 val 字段的音频数据时,客户端应该进行正确的转换和验证,确保其是有效的音频数据,以防止恶意内容被播放或执行。

BN: 交互按钮

``BN提供了向服务器发送数据的选项,可以是原始服务器或其他服务器。data` 包含以下字段:

{"tp": "BN","data": {"name": "confirmation","act": "url","val": "some-value","ref": "https://www.example.com/path/?foo=bar"}
}
  • act: 按钮点击后的操作类型:
    • pub: 发送一个 Drafty 格式的 {pub} 消息到当前聊天会话中(私聊或者群),其中包含表单数据作为附件:
    { "tp":"EX", "data":{ "mime":"application/json", "val": { "seq": 3, "resp": { "confirmation": "some-value" } } } }
    
    • url: 发送一个 HTTP GET 请求到 data.ref 字段中的 URL。以下查询参数将附加到 URL 中:<name>=<val>uid=<current-user-ID>topic=<topic name>seq=<message sequence ID>
    • note: 发送一个 {note} 消息到当前主题,what 设置为 data
    { "what": "data", "data": { "mime": "application/json", "val": { "seq": 3, "resp": { "confirmation": "some-value" } } } }
    
  • name: 按钮的可选名称,将报告给服务器。
  • val: 附加的不透明数据。
  • ref: url 操作的 URL。

如果提供了 name 但未提供 val,则假定 val1。如果未定义 name,则不会发送 nameval

上面示例中的按钮将向

https://www.example.com/path/?foo=bar&confirmation=some-value&uid=usrFsk73jYRR&topic=grpnG99YhENiQU&seq=3

发送一个 HTTP GET 请求,假设当前用户 ID 为 usrFsk73jYRR,主题为 grpnG99YhENiQU,带有按钮的消息的序列 ID 为 3

重要安全注意事项:客户端应该将 ref 字段中的 URL 方案限制为仅允许 httphttps

EX: 文件附件

EX 是一个附件,示例如下:

{"tp": "EX","data": {"mime", "text/plain","val", "Q3l0aG9uPT0w...PT00LjAuMAo=","ref": "/v0/file/s/abcdef12345.txt","name", "requirements.txt","size": 1234}
}
  • mime: 数据类型,例如 ‘application/octet-stream’。
  • val: 可选的内联 base64 编码的文件数据。
  • ref: 可选的外部文件数据引用。valref 必须二选一。
  • name: 原始文件的可选名称。
  • size: 文件的可选大小(以字节为单位)。

To generate a message with the file attachment shown as a downloadable file, use the following format:

{at: -1,len: 0,key: <EX entity reference>
}
IM: 内联图或者引用图

IM 是一个图片;data 包括如下字段:

{"tp": "IM","data": {"mime": "image/png","val": "Rt53jUU...iVBORw0KGgoA==","ref": "/v0/file/s/abcdef12345.jpg","width": 512,"height": 512,"name": "sample_image.png","size": 123456}
}
  • mime: 数据类型,例如 ‘image/jpeg’。
  • val: 可选的内联图像数据:base64 编码的图像位。
  • ref: 可选的外部图像数据引用。valref 必须二选一。
  • widthheight: 图像的线性尺寸,以像素为单位。
  • name: 原始文件的可选名称。
  • size: 文件的可选大小(以字节为单位)。

如果发送一个没有文本的纯图片,格式如下:

{txt: " ",fmt: [{len: 1}],ent: [{tp: "IM", data: {<your image data here>}]}
}

_重要安全注意事项valref 字段可能包含恶意有效负载。客户端应该限制 ref 字段中的 URL 方案仅限于 httphttps。客户端应该仅当 val 字段正确转换为图像时才向用户呈现其内容。

LN: 链接 (URL)

LN 表示一个URL链接。data 包含一个字段 url,其值为URL链接的地址,例如 "https://www.example.com/abc#fragment"

MN 表示提及某人,比如 @alicedata 包含一个字段 val,其值为被提及用户的ID,例如

{ "tp":"MN", "data":{ "val":"usrFsk73jYRR" } }

HT 表示标签,例如 #tinode

data 包含一个字段 val,其值为标签的值,例如

{ "tp":"HT", "data":{ "val":"tinode" } }
VC: 视频电话控制信息

视频通话 data 包含当前的视频电话的状态和时长等:

{"tp": "VC","data": {"duration": 10000,"state": "disconnected","incoming": false,"aonly": true}
}

VC 表示视频通话控制消息。data 包含以下字段:

  • duration:通话持续时间,单位为毫秒。
  • state:当前通话状态;支持的状态有:
    • accepted:通话已建立(进行中)。
    • busy:由于被呼叫方已经在另一个通话中,因此无法建立通话。
    • finished:之前建立的通话已成功结束。
    • disconnected:通话被中断,例如因为错误。
    • missed:通话未接听,即被呼叫方未接听电话。
    • declined:通话被拒绝,即被呼叫方在接听之前挂断电话。
  • incoming:如果通话是呼入的,则为 true;否则为 false。
  • aonly:如果这是一个仅音频通话(无视频),则为 true。

VC 也可以表示为格式 "fmt": [{"len": 1, "tp": "VC"}],在这种情况下,所有通话信息都包含在外部消息的 head 字段中。

VD: 带预览的视频

``VD 表示视频录制。data` 包含以下字段:

{"tp": "VD","data": {"mime": "video/webm","ref": "/v0/file/s/abcdef12345.webm","preview": "AsTrsU...k86n00Ggo==""preref": "/v0/file/s/abcdef54321.jpeg","premime": "image/jpeg","width": 640,"height": 360,"duration": 32000,"name": " bigbuckbunny.webm","size": 1234567}
}
  • mime: 视频数据类型,例如 ‘video/webm’。
  • val: 可选的内联视频数据:base64编码的视频数据,通常不存在(null)。
  • ref: 可选的外部视频数据的引用。valref 必须至少存在一个。
  • preview: 可选的视频截图的 base64 编码图像(封面图)。
  • preref: 可选的视频截图的外部引用(封面图)。
  • premime: 可选的视频截图的数据类型(封面图);如果缺少,默认为’image/jpeg’。
  • widthheight: 视频和封面图的线性尺寸(像素)。
  • duration: 视频的时长(毫秒)。
  • name: 原始文件的可选名称。
  • size: 文件的可选大小(字节)。

一个没有文本的视频消息如下:

{txt: " ",fmt: [{len: 1}],ent: [{tp: "VD", data: {<your video data here>}]}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/18842.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IMX6Q基于kernel3.0.35版本调试GT9xx触摸屏

IMX6Q基于kernel3.0.35版本调试GT9xx触摸屏 1、开发环境2、推荐指数3、开发过程4、文件系统环境变量1、开发环境 芯片:IMX6Q (NXP系列) 内核版本:linux3.0.35 Ubuntu版本:16.04 移植的触摸芯片:GT911 2、推荐指数 GT9xx的触摸型号驱动基本上现在网上的文章都比比皆是,…

PyTorch自定义张量操作开发指南【CFFI+CUDA】

PyTorch 与 TensorFlow 一起成为深度学习研究人员和从业者的标准。虽然 PyTorch 在张量运算或深度学习层方面提供了多种选择&#xff0c;但一些专门的操作仍然需要手动实现。在运行时至关重要的情况下&#xff0c;应使用 C 或 CUDA 来完成此操作&#xff0c;以支持 CPU 和 GPU …

linux系统——htop命令检测

在之前提到top命令可以检测进程情况&#xff0c;但需要额外一些参数才能更清晰得到一些数据&#xff0c;htop也是进程监测命令&#xff0c;但更为准确&#xff0c;给出信息更为详实

H2RSVLM:引领遥感视觉语言模型的革命

随着人工智能技术的飞速发展&#xff0c;遥感图像理解在环境监测、气候变化、粮食安全和灾害预警等多个领域扮演着越来越重要的角色。然而&#xff0c;现有的通用视觉语言模型&#xff08;VLMs&#xff09;在处理遥感图像时仍面临挑战&#xff0c;主要因为遥感图像的独特性和当…

stream-实践应用-统计分析

背景 业务部门提供了一个数据&#xff0c;数据甚至不是excel类型的&#xff0c;是data.txt&#xff0c;每一行都是一个数据&#xff0c;需要对此数据进行统计分析 统计各个月份的销量 因为直接获取resources下的data.txt&#xff0c;所以要借助输入流进行获取数据&#xff0c;再…

【手把手带你微调 Llama3】 改变大模型的自我认知,单卡就能训

微调Llama3的自我认知后 当你问Llama3中文问题&#xff1a; “你叫什么名字&#xff1f;”、 “做个自我介绍”、 “你好” Llama3 会用中文回答 &#xff1a; “我是AI在手” &#xff08;如下图&#xff09; 1、环境安装 # nvidia 显卡 显存16G# pytorch 2.2.2 …

自然语言处理学习中英文翻译语料库

在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;学习中英文翻译需要高质量的双语语料库。以下是一些常用的中英文翻译语料库资源&#xff1a; OpenSubtitles&#xff1a; 网站&#xff1a; OpenSubtitles 描述&#xff1a;OpenSubtitles 提供了大量的电影和电视剧…

JavaScript四种输出

window.alert()&#xff1a; 使用警告框来显示数据 如&#xff1a; <!DOCTYPE html> <html> <body> <script>window.alert("我来了"); </script></body> </html> 浏览器打开就会显示一个弹窗“我来了” innerHTML&…

VUE项目引入微信JSSDK 使用微信api

大佬地址&#xff1a;VUE项目引入微信JSSDK 实现微信自定义分享_vue中如何引入wx sdk-CSDN博客 支付功能&#xff1a; 第一个接口 是初始化 ssdk的 第二个接口 是调用微信支付的 jsApiPayBefore().then(res > {let getMsg res.dataswx.config({debug: false, //生产环境需…

【Java】【python】leetcode刷题记录--双指针

双指针也一般称为快慢指针&#xff0c;主要用于处理链表和数组等线性数据结构。这种技巧主要涉及到两个指针&#xff0c;一个快指针&#xff08;通常每次移动两步&#xff09;和一个慢指针&#xff08;通常每次移动一步&#xff09;。快指针可以起到’探路‘的作用&#xff0c;…

S32K --- FLS MCAL配置

一、前言 二、MCAL配置 添加一个Mem_43_infls的模块, infls是访问内部flash, exfls是访问外部flash 2.1 General 这边暂时保持的默认,还没详细的去研究,等有空研究了,我再来更新 2.2 MemInstance 双金“index”的下标“0”可以进里面详细配置,这个是基本操作了。 2.2.1 G…

关于Word目录的更新

左侧标题顺序如有调整&#xff0c;自动目录并不会同步更新&#xff0c;每次都要记得在正文目录左上角点击更新目录

2024-05-29 服务器开发-c++线程池与task-思考

摘要: 无论是什么系统&#xff0c;线程池和task都是给上层所提供的基础的功能单元。本文记录一些核心的设计思想。 线程池要面对的场景: 调用下层接口时&#xff0c;被IO阻塞&#xff0c;导致整个服务无法对外提供服务更上层调用本模块接口时&#xff0c;是需要做到同步&#…

【nnUNetv2进阶】十、nnUNetv2 魔改网络-小试牛刀-引入注意力机制EPSA

nnUNet是一个自适应的深度学习框架,专为医学图像分割任务设计。以下是关于nnUNet的详细解释和特点: 自适应框架:nnUNet能够根据具体的医学图像分割任务自动调整模型结构、训练参数等,从而避免了繁琐的手工调参过程。 自动化流程:nnUNet包含了从数据预处理到模型训练、验证…

Vue 3 中的 emit(‘update_modelValue‘):更灵活的双向绑定

你好&#xff0c;我是小白Coding日志&#xff0c;一个热爱技术的程序员。在这里&#xff0c;我分享自己在编程和技术世界中的学习心得和体会。希望我的文章能够给你带来一些灵感和帮助。欢迎来到我的博客&#xff0c;一起在技术的世界里探索前行吧&#xff01; 随着 Vue 3 的发…

面向链接预测的知识图谱表示学习方法综述

源自&#xff1a;软件学报 作者&#xff1a;杜雪盈, 刘名威, 沈立炜, 彭鑫 注&#xff1a;若出现无法显示完全的情况&#xff0c;可搜索“人工智能技术与咨询”查看完整文章 摘 要 作为人工智能的重要基石, 知识图谱能够从互联网海量数据中抽取并表达先验知识, 极大程度解决…

开源基于Node编写的批量HTML转PDF

LTPP批量HTML转PDF工具 Github 地址 LTPP-GIT 地址 官方文档 功能 LTPP 批量 HTML 转 PDF 工具支持将当前目录下所有 HTML 文件转成 PDF 文件&#xff0c;并且在新目录中保存文件结构与原目录结构一致 说明 一共两个独立版本&#xff0c;html-pdf 目录下是基于 html-pdf 模…

代码随想录算法训练营day38 | 435. 无重叠区间、763.划分字母区间、56. 合并区间

435. 无重叠区间 按照左边界排序&#xff0c;直接求重叠区间 class Solution:def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:if len(intervals) < 1:return 0intervals.sort(keylambda x: x[0])end intervals[0][1]result 0for i in range(1,…

【CALayer-时钟练习-旋转 Objective-C语言】

一、好,接下来呢,我们要让它旋转出来, 1.让它先旋转起来啊,这根秒针,让它先转着, 把之前的代码复制粘贴一份,改个名字,叫:07-时钟练习(旋转) 旋转的话,我现在应该让它,一秒钟,旋转一次,一秒钟,旋转一次, 那么,这个时候,我们应该怎么样去做, 我现在这个是…

便携式应急气象站:应急气象监测装备

TH-BQX5便携式应急气象站&#xff0c;作为现代气象监测的重要装备&#xff0c;以其独特的便携性、高效性和灵活性&#xff0c;在应急气象监测领域发挥着至关重要的作用。这类气象站不仅为灾害预警、环境保护、农业生产等多个领域提供了实时、准确的气象数据&#xff0c;还在突发…