mcdanlj
(Michael K Johnson)
1
在工作中,我们大量使用 Slack。有一些内容需要在 Slack 上可访问,但同时需要良好的组织和搜索功能,而这两点正是 Discourse 的强项。我们尝试过几种类似维基的解决方案,但它们都逐渐被弃用,部分原因是与 Slack 缺乏关联。因此,我正在推动对 Discourse 的评估,使其与现有的 Slack 并行运行并实现连接,因为我已经在运营一个 Discourse 社区论坛了。
然而,我们有很多频道都积极使用线程功能。这包括优先级最高的 Slack 频道,需要在 Discourse 和 Slack 之间进行双向(watch 和 post)集成。
如果让 chat-integrations 插件支持一种非默认模式:将新主题作为消息发布到 Slack,存储 Slack 消息 ID 与主题的关联,然后将该主题的新评论作为线程消息发送到 Slack,这样是否会破坏该插件的设计?对于我的使用场景来说,这可能是成功与失败的关键区别。
更新:针对我的使用场景,这应该是 watch 的一个选项,而不是全站范围的 Slack 聊天配置,因为“偏好使用线程”或“偏好不使用线程”是基于 Slack 频道的目的(以及典型参与者)的每个频道的偏好设置。
4 个赞
david
(David Taylor)
2
这听起来是个很棒的主意!将其添加到插件中绝对是 pr-welcome(欢迎提交拉取请求)
确认一下……你说的“发布”是指现有的转录发布功能吗?还是你想让 Slack 线程与 Discourse 主题“同步”?我认为后者实现起来相当复杂,可能不适合放入 chat-integration 插件中。
1 个赞
mcdanlj
(Michael K Johnson)
4
不,我们并不是试图双向同步单个线程,以便你可以在任意一侧发帖并让另一侧同步显示。我曾负责在两个非常活跃的域之间实现完全双向的同步,因此我深知其中容易出错的地方。
我们的场景是一个频道,其中:
- 线程化回复是常态,因为该频道往往同时收集多个不相关主题的对话(该频道是面向业务目的而非特定主题设立的;如果不这样做,一个不切实际的替代方案就是每天创建十几个临时频道,并邀请一半的工程人员加入)
- 其中许多(但非全部)线程化对话应被识别为回答了他人的问题,且后续有人希望查阅这些答案。我们会通过集成将这些内容提升为与 Discourse 中相应分类相关的可信内容(例如由我这样的专人主动筛选有价值的回答)
- 在 Discourse 中创建该相关分类下的新主题时,应自动在对应的 Slack 频道中发布帖子
- 这些新主题下的后续评论应以线程形式发布到 Slack,跟随最初的 Slack 帖子
- 我们的用户被引导在 Slack 提问前先搜索 Discourse
此外,你提出这个问题让我想到,作为一个相关功能,如果在将 Slack 线程总结为 Discourse 帖子时,集成能够自动在原始 Slack 线程末尾添加指向新 Discourse 主题的链接,那将非常有用。这将有助于我们将讨论集中在一个地方。
这实际上与最初的功能构想密切相关:如果我们同时具备这两项功能,那么当总结 Slack 线程时,与其发布一条新的 Slack 消息,不如将消息发布到被总结的线程中,并标记该线程为后续 Discourse 评论的发布位置。这样,该线程中的额外 Slack 评论将不会被总结到 Discourse 中,而是旨在将讨论引导至 Discourse 上关于该主题的讨论。这在我看来是合乎逻辑的:
- 前提:存在一个地方可以存储与主题关联的 Slack 消息 ID
- 并且:主题的新评论作为对该存储的 Slack 消息的评论发布
- 结果:在使用
post thread Slackbot 集成功能时,将 Slack 消息 ID 与主题关联,从而使该主题上的新 Discourse 评论在该线程中发布通知,并包含指向 Discourse 主题/评论的链接
这将极大地帮助推广“提问前先查看 Discourse”的理念。
5 个赞
riking
(Kane York)
6
作为视觉辅助,这是否看起来像您想要推广的 Slack 端用户体验?
……哦天哪,线程发起者的年份被省略了。大家猜猜看?
mcdanlj
(Michael K Johnson)
7
@riking 有一点,但存在一些差异。
公告的样式不会完全像那样;它将由集成的 watch 端发布。它不会说明帖子已被移动。以下是我目前为 makerforums 实现的(非线程化)接口示例,来自 Slack 集成:
在线程化模型中,这些帖子中的第一条会启动一个 Slack 线程,而 Nedman 的评论则会作为该 Slack 线程中的回复出现。当使用 post thread :thread_url 时,:thread_url 会被存储到新主题中,集成的 watch 端会发布初始主题帖子以及后续所有评论到该 Slack 线程,但内容保持不变。
watch thread 集成会将你引导至 Discourse,在那里你需要撰写标题,并有机会在发布前编辑新主题帖。因此,发布到 Slack 的公告会先注明运行 post thread 的人是作者,然后是一行包含主题标题的链接文本(指向 Discourse),接着是帖子开头的引用摘录。我在此提出的变更是:通过非默认且按频道配置的方式(即 watch 选项,而非全站聊天集成插件配置),将该内容发布到线程中,而不是发布到频道中。(不是“也发送到频道”——那将违背我们进行此变更的初衷。)在 Discourse 中对该新主题的任何进一步评论也会进入同一个 Slack 线程。
另外,既然你问到了猜测,那就是 2017 年,Slack 推出线程功能的那一年?
2 个赞
mcdanlj
(Michael K Johnson)
8
我一直在思考这个问题,并阅读了 chat.postMessage Slack API 文档,我相信可以将我的一大段文字简化为更简洁的方案。
只有 watch(而非 follow)具备选择线程回复的能力,其机制我仍在研究中。或者,@david,您觉得是否可以考虑新增一个 thread 规则过滤器,优先级顺序为 mute > thread > watch > follow,并将该规则通过 trigger_notification 传递,以实现基于规则的敏感行为?
-
如果 watch 配置为启用线程(或者定义了 thread 规则),在向 Slack 频道发送新帖子通知时,若该帖子主题已关联一个 Slack ts,则通过将 thread_ts 设置为从 Slack 提供的 ts 值,将消息发布到对应的 Slack 线程中。
-
在向 Slack 频道发送新帖子通知时,若该帖子主题尚未关联任何 ts,则存储返回响应中的 ts(以便后续该主题的帖子在 watch 配置为启用线程时能够进行线程化)。
-
当使用 post thread :thread_url 命令时,将线程的 ts 存储到所创建的主题中,该值将仅被支持线程的 watch 规则使用。
以下是我目前的想法和顾虑:
-
如何按规则决定是否为线程发帖。目前我觉得新增一个过滤器是最简单的方案,但也许我遗漏了什么。
-
将原始 Slack 帖子 URL 和线程 ID 贯穿整个转录流程,目前对我来说是最不清晰的部分。这看起来确实需要在某个地方为每个提供商添加一个线程 ID,并一直保留到保存帖子时为止。我目前计划仅针对 Slack 的 ts 实现该功能,但预计未来不会只有 Slack 这一种支持线程的聊天集成。
-
关于发帖,我认为需要在 Topic 上为 Slack 存储一个 Slack 特定的自定义字段(而非通用的 DiscourseChat 自定义线程字段)来保存 Slack 的 ts。
1 个赞
david
(David Taylor)
9
‘threading’布尔值真的需要按规则设置吗?为什么不创建一个新站点设置
chat_integration_slack_thread_responses
如果启用该设置,并且我们拥有主题的线程 ID 记录,那么后续通知就会发送到 Slack 线程中。
是的,我觉得这完全没问题。只需使用特定于 Slack 的主题自定义字段即可。如果我们日后觉得有必要为其他提供商实现此功能,可以将解决方案设计得更通用。
是的,这确实很棘手。作为 v1 版本,我倾向于在帖子顶部包含类似
<!--SLACK_THREAD_ID=abcdefg-->
的内容。然后插件可以检查以该字符串开头的帖子,并分配自定义字段。这并不完美,但或许是一个不错的起点?
2 个赞
mcdanlj
(Michael K Johnson)
10
非常感谢!
昨晚,我实现了前两个 AC(验收标准),并在整个技术栈中通过了所有测试(尽管尚未进行实时测试),但尚未测试转录流程。我使用了 Topic 上的一个自定义字段和一个 thread 规则。因此,在能够至少在草稿 PR 中展示代码方面,进展顺利。
我还有一个单独的提交,用于移除 Slack 提供者中未使用的 pstore_get。既然 pstore 在整个技术栈中仅此一处使用,您是否希望我在那个清理提交中也一并移除 app/initializers/discourse_chat.rb 中所有的 pstore_* 相关代码?
这正是我最初的出发点,那样确实会简单得多!
不过,至少就我的使用场景而言(我也听到其他公司的同事有类似反馈,我们并非特例),不同频道对于是否使用线程有不同的偏好。有些频道设计为使用线程(因为大多数人只关注某些特定话题),而有些频道则强烈反对线程(因为线程会掩盖重要信息)。
我观察到主要有两个本质上不相关的因素在驱动这种偏好:
- 成员构成:大多数成员使用 IRC 数十年的频道,习惯于在单一频道中通过心理区分交织的对话线程,不希望为了查看重要内容而点击进入线程;而大多数成员习惯于电子邮件的频道则期望对话是线程化的,并愿意点击进入他们关心的对话。
- 用途:具有公告业务目的的频道往往积极采用线程化,而用于研究或协作的频道则通常故意不采用线程化,因为线程会隐藏信息,除非用户注意到并点击进入。
如果您希望为规则选项提供某种通用的语法,我认为可以扩展 Rule,使其拥有一个 :options 值,该值与 :tags 类似,也是一个数组。或许可以借鉴命令行 shell 的做法,例如 /discourse [watch|follow|mute] -something -here 会将 :options 设置为 ['something', 'here'],即保留前导 - 来引入选项。那么命令就可以写成 /discourse watch my-category-slug #tagged-foo -threaded。我不确定这比我目前所做的会增加多少工作量。您对此是否有强烈的倾向?我可以看到两种观点的论据:在 Rule 中添加另一个值会使编写聊天提供者变得更加复杂;添加另一个过滤值则会使另一个 Slack 特定功能(如发布转录)变得更加复杂,从而增加非 Slack 用户的使用难度。当然,我可能遗漏了一些会让这比我想象的更困难的细节;例如,如果类别 slug 可以以 - 开头,就会导致歧义;shell 使用 -- 表示“此后的内容都不是参数”,或许我们可以反过来,让 -- 表示“此后的内容都是选项”。如果您希望我研究这一点,请就规则选项的语法提供指导。不过,对我来说,直接添加 thread 似乎更简单,因此,如果没有明确要求添加通用的“选项”功能,我将暂不朝这个方向做任何更改。
[编辑:将规则过滤器改为选项肯定会增加 UI 的复杂性,UI 必须扩展以支持通用的选项功能,这在我看来并不是一个很好的选择。因此,在查看了 UI 之后,我更倾向于坚持使用过滤器;我认为这样更清晰。]
关于帖子转录流程,感谢您提出的 HTML 注释建议。对于我的使用场景来说,这并不会造成任何困扰;说实话,我预计自己至少在初期将是主要用户。这是一个简单而巧妙的技巧。
我还有一个 separate 的想法,不打算包含在这个 PR 中:如果能有一个从消息所属频道到目标 Discourse 帖子所属分类的映射,那就太好了。为了实现这一点,我认为转录最好改为包含一个信封(envelope)或侧车(sidecar),此时信封或侧车可以同时包含类别和 Slack ID。这对我来说似乎需要大量的学习,因为我目前仍处于“通过高级谷歌搜索解决问题”的 Ruby on Rails 学习阶段。
2 个赞
mcwumbly
(Dave McClure)
11
关于为这个功能锦上添花的另一个想法:
是否可以添加另一个设置项,例如 cross_post_to_channel_after_hours(默认值设为 48 小时?),当距离上次回复的时间超过 x 小时,帖子就会被发送到该线程,并附带“同时发送到频道”的标记。
如果您目前只想先让功能正常运行,暂时不必太在意我的建议(这或许是个更好的策略!)。仅供您参考…
mcdanlj
(Michael K Johnson)
12
这绝不是一个疯狂的想法,但我并不打算实现它,因为这会破坏我的主要使用场景,而且我在其他地方也不需要它。
不过,我完全理解其他人会有这样的需求!
如果这是一个常规设置而不是每个频道独立的选项,那么它应该叫 chat_integration_slack_copy_threads_to_channel_after_hours,默认值为 0(不发送),但你可以将其设置为任意值。从概念上讲它相当简单,但需要更多工作,因为你必须获取线程(使用最初为转录功能编写的代码,我不确定是否需要重构),以便决定是否设置一个简单的标志。
但如果你愿意着手实现它,我希望我所做的工作能提供一个良好的框架。我只请求你不要默认开启它,因为如果在升级时默认启用,而我的用户因为我整理内容到 Discourse 而收到“垃圾信息”,那就会引发用户的不满。
1 个赞
mcwumbly
(Dave McClure)
13
为了简化问题,我认为你可以直接检查 Discourse 主题中上一条帖子的日期。
(在某些情况下它的行为会略有不同,但可以作为不错的起点)
mcdanlj
(Michael K Johnson)
14
@david 我提交了一个 草稿 PR,它通过了我编写的单元测试。我还没有尝试在 Slack 上实际运行它,所以在完成之前我不想合并它。但至少所有单元测试都通过了,我也尝试为它们添加了有意义的测试。
我还将 ID 注释放在了帖子的末尾而不是开头,因为我觉得这样更有可能被保留下来,而不会被篡改,并且我尝试在解析时保持谨慎。
感谢你们对这个插件的贡献!
我修复了最初的代码规范检查失败,但现在一些我没有触碰的测试却失败了。我的代码基于最新的 master 分支,本地测试是通过的。你对这些失败的测试有什么见解吗?
4 个赞
mcdanlj
(Michael K Johnson)
15
我已经对 PR 做了大量清理,但尚未完全准备好。目前有两三处问题让我感到棘手,我还不清楚如何解决。
-
我尝试使用 fa-arrow-circle-o-right 作为线程图标,但在我的在线站点 UI 中显示为空。(在检出我的分支后,我会在在线站点上运行 su discourse -c 'bundle exec rake assets:precompile' && sv restart unicorn 以在实时服务器上进行测试。)我已在 plugin.rb 中添加了该图标并进行了引用,但接下来该怎么做我有些迷茫。Discourse 是否有一份获准使用的 FontAwesome 图标列表? 我找到了 lib/svg_sprite/svg_sprite.rb,其中的 chevron-right 非常适合此用途。
-
本地测试全部通过,但在 Travis 中我持续遇到一些看似与我的更改无关的错误,这自然让我难以调查或分析。在 spec/lib/discourse_chat/provider/slack/slack_command_controller_spec.rb 中有 13 个失败,返回的是 404 而非预期的其他状态码(例如 200)。 通过不再盲目复制 isolate_namespace 并学会使用 rake routes 已解决此问题。
我已成功发布:
可能还有需要清理的地方,但我觉得这已经可以工作了。
合并之后,我会相应地更新 https://meta.discourse.org/t/chatroom-integration-plugin-discourse-chat-integration/66522/1。
2 个赞
mcdanlj
(Michael K Johnson)
16
我不断在这里发现新的学习机会。现在我知道了如何运行 yarn prettier,接下来我要学习如何更新前端测试……
错误:断言失败:您必须使用 set() 来设置 `channel` 属性(对象为 <(unknown):ember3806>)的值为 `<(unknown):ember3799>`。
david
(David Taylor)
17
非常感谢你在这里的所有工作 @mcdanlj —— 现已合并:
4 个赞
mcdanlj
(Michael K Johnson)
18
非常感谢你们非常有益的评论!我按承诺更新了官方集成维基帖子。如果你希望用其他方式指出这些变更,我完全没问题,我没有所谓的作者自尊心之类的东西。
3 个赞
sunjam
(james.network)
19
能否在 Slack 的聊天集成设置中启用线程功能,就像
启用帖子到 Slack 的线程 一样?
mcdanlj
(Michael K Johnson)
20
您的意思是,您希望配置该插件,使其在集成中拒绝响应 thread 选项?
sunjam
(james.network)
21
我们几天前已更新至当前的 2.6 beta1a 版本,测试已通过。但据我所知,升级后 Slack 的跨频道帖子仍未形成线程。在 Slack 频道中,主题帖和回复仍以单独的形式显示。