github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/services/sharedchannel/permalink.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package sharedchannel 5 6 import ( 7 "context" 8 "net/url" 9 "regexp" 10 "strings" 11 12 "github.com/masterhung0112/hk_server/v5/model" 13 "github.com/masterhung0112/hk_server/v5/shared/i18n" 14 "github.com/masterhung0112/hk_server/v5/shared/mlog" 15 ) 16 17 var ( 18 // Team name regex taken from model.IsValidTeamName 19 permaLinkRegex = regexp.MustCompile(`https?://[0-9.\-A-Za-z]+/[a-z0-9]+([a-z\-0-9]+|(__)?)[a-z0-9]+/pl/([a-zA-Z0-9]+)`) 20 permaLinkSharedRegex = regexp.MustCompile(`https?://[0-9.\-A-Za-z]+/[a-z0-9]+([a-z\-0-9]+|(__)?)[a-z0-9]+/plshared/([a-zA-Z0-9]+)`) 21 ) 22 23 const ( 24 permalinkMarker = "plshared" 25 ) 26 27 // processPermalinkToRemote processes all permalinks going towards a remote site. 28 func (scs *Service) processPermalinkToRemote(p *model.Post) string { 29 var sent bool 30 return permaLinkRegex.ReplaceAllStringFunc(p.Message, func(msg string) string { 31 // Extract the postID (This is simple enough not to warrant full-blown URL parsing.) 32 lastSlash := strings.LastIndexByte(msg, '/') 33 postID := msg[lastSlash+1:] 34 postList, err := scs.server.GetStore().Post().Get(context.Background(), postID, true, false, false, "") 35 if err != nil { 36 scs.server.GetLogger().Log(mlog.LvlSharedChannelServiceWarn, "Unable to get post during replacing permalinks", mlog.Err(err)) 37 return msg 38 } 39 if len(postList.Order) == 0 { 40 scs.server.GetLogger().Log(mlog.LvlSharedChannelServiceWarn, "No post found for permalink", mlog.String("postID", postID)) 41 return msg 42 } 43 44 // If postID is for a different channel 45 if postList.Posts[postList.Order[0]].ChannelId != p.ChannelId { 46 // Send ephemeral message to OP (only once per message). 47 if !sent { 48 scs.sendEphemeralPost(p.ChannelId, p.UserId, i18n.T("sharedchannel.permalink.not_found")) 49 sent = true 50 } 51 // But don't modify msg 52 return msg 53 } 54 55 // Otherwise, modify pl to plshared as a marker to be replaced by remote sites 56 return strings.Replace(msg, "/pl/", "/"+permalinkMarker+"/", 1) 57 }) 58 } 59 60 // processPermalinkFromRemote processes all permalinks coming from a remote site. 61 func (scs *Service) processPermalinkFromRemote(p *model.Post, team *model.Team) string { 62 return permaLinkSharedRegex.ReplaceAllStringFunc(p.Message, func(remoteLink string) string { 63 // Extract host name 64 parsed, err := url.Parse(remoteLink) 65 if err != nil { 66 scs.server.GetLogger().Log(mlog.LvlSharedChannelServiceWarn, "Unable to parse the remote link during replacing permalinks", mlog.Err(err)) 67 return remoteLink 68 } 69 70 // Replace with local SiteURL 71 parsed.Scheme = scs.siteURL.Scheme 72 parsed.Host = scs.siteURL.Host 73 74 // Replace team name with local team 75 teamEnd := strings.Index(parsed.Path, "/"+permalinkMarker) 76 parsed.Path = "/" + team.Name + parsed.Path[teamEnd:] 77 78 // Replace plshared with pl 79 return strings.Replace(parsed.String(), "/"+permalinkMarker+"/", "/pl/", 1) 80 }) 81 }