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  }