mattermost-community-enterp.../platform/services/slackimport/converters.go
Claude ec1f89217a Merge: Complete Mattermost Server with Community Enterprise
Full Mattermost server source with integrated Community Enterprise features.
Includes vendor directory for offline/air-gapped builds.

Structure:
- enterprise-impl/: Enterprise feature implementations
- enterprise-community/: Init files that register implementations
- enterprise/: Bridge imports (community_imports.go)
- vendor/: All dependencies for offline builds

Build (online):
  go build ./cmd/mattermost

Build (offline/air-gapped):
  go build -mod=vendor ./cmd/mattermost

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 23:59:07 +09:00

151 lines
4.0 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package slackimport
import (
"regexp"
"strconv"
"strings"
"github.com/mattermost/mattermost/server/public/shared/mlog"
)
func slackConvertTimeStamp(ts string) int64 {
timeString := strings.SplitN(ts, ".", 2)[0]
timeStamp, err := strconv.ParseInt(timeString, 10, 64)
if err != nil {
mlog.Warn("Slack Import: Bad timestamp detected.")
return 1
}
return timeStamp * 1000 // Convert to milliseconds
}
func slackConvertChannelName(channelName string, channelId string) string {
newName := strings.Trim(channelName, "_-")
if len(newName) == 1 {
return "slack-channel-" + newName
}
if isValidChannelNameCharacters(newName) {
return newName
}
return strings.ToLower(channelId)
}
func slackConvertUserMentions(users []slackUser, posts map[string][]slackPost) map[string][]slackPost {
var regexes = make(map[string]*regexp.Regexp, len(users))
for _, user := range users {
r, err := regexp.Compile("<@" + user.Id + `(\|` + user.Username + ")?>")
if err != nil {
mlog.Warn("Slack Import: Unable to compile the @mention, matching regular expression for the Slack user.", mlog.String("user_name", user.Username), mlog.String("user_id", user.Id))
continue
}
regexes["@"+user.Username] = r
}
// Special cases.
regexes["@here"], _ = regexp.Compile(`<!here\|@here>`)
regexes["@channel"], _ = regexp.Compile("<!channel>")
regexes["@all"], _ = regexp.Compile("<!everyone>")
for channelName, channelPosts := range posts {
for postIdx, post := range channelPosts {
for mention, r := range regexes {
post.Text = r.ReplaceAllString(post.Text, mention)
posts[channelName][postIdx] = post
}
}
}
return posts
}
func slackConvertChannelMentions(channels []slackChannel, posts map[string][]slackPost) map[string][]slackPost {
var regexes = make(map[string]*regexp.Regexp, len(channels))
for _, channel := range channels {
r, err := regexp.Compile("<#" + channel.Id + `(\|` + channel.Name + ")?>")
if err != nil {
mlog.Warn("Slack Import: Unable to compile the !channel, matching regular expression for the Slack channel.", mlog.String("channel_id", channel.Id), mlog.String("channel_name", channel.Name))
continue
}
regexes["~"+channel.Name] = r
}
for channelName, channelPosts := range posts {
for postIdx, post := range channelPosts {
for channelReplace, r := range regexes {
post.Text = r.ReplaceAllString(post.Text, channelReplace)
posts[channelName][postIdx] = post
}
}
}
return posts
}
func slackConvertPostsMarkup(posts map[string][]slackPost) map[string][]slackPost {
regexReplaceAllString := []struct {
regex *regexp.Regexp
rpl string
}{
// URL
{
regexp.MustCompile(`<([^|<>]+)\|([^|<>]+)>`),
"[$2]($1)",
},
// bold
{
regexp.MustCompile(`(^|[\s.;,])\*(\S[^*\n]+)\*`),
"$1**$2**",
},
// strikethrough
{
regexp.MustCompile(`(^|[\s.;,])\~(\S[^~\n]+)\~`),
"$1~~$2~~",
},
// single paragraph blockquote
// Slack converts > character to &gt;
{
regexp.MustCompile(`(?sm)^&gt;`),
">",
},
}
regexReplaceAllStringFunc := []struct {
regex *regexp.Regexp
fn func(string) string
}{
// multiple paragraphs blockquotes
{
regexp.MustCompile(`(?sm)^>&gt;&gt;(.+)$`),
func(src string) string {
// remove >>> prefix, might have leading \n
prefixRegexp := regexp.MustCompile(`^([\n])?>&gt;&gt;(.*)`)
src = prefixRegexp.ReplaceAllString(src, "$1$2")
// append > to start of line
appendRegexp := regexp.MustCompile(`(?m)^`)
return appendRegexp.ReplaceAllString(src, ">$0")
},
},
}
for channelName, channelPosts := range posts {
for postIdx, post := range channelPosts {
result := post.Text
for _, rule := range regexReplaceAllString {
result = rule.regex.ReplaceAllString(result, rule.rpl)
}
for _, rule := range regexReplaceAllStringFunc {
result = rule.regex.ReplaceAllStringFunc(result, rule.fn)
}
posts[channelName][postIdx].Text = result
}
}
return posts
}