github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/cmd/hkserver/commands/sampledata.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package commands
     5  
     6  import (
     7  	"encoding/json"
     8  	"errors"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"math/rand"
    12  	"os"
    13  	"path"
    14  	"sort"
    15  	"strings"
    16  	"time"
    17  
    18  	"github.com/icrowley/fake"
    19  	"github.com/spf13/cobra"
    20  
    21  	"github.com/masterhung0112/hk_server/v5/app"
    22  	"github.com/masterhung0112/hk_server/v5/app/request"
    23  	"github.com/masterhung0112/hk_server/v5/audit"
    24  	"github.com/masterhung0112/hk_server/v5/model"
    25  	"github.com/masterhung0112/hk_server/v5/utils"
    26  )
    27  
    28  const (
    29  	DeactivatedUser = "deactivated"
    30  	GuestUser       = "guest"
    31  )
    32  
    33  var SampleDataCmd = &cobra.Command{
    34  	Use:   "sampledata",
    35  	Short: "Generate sample data",
    36  	RunE:  sampleDataCmdF,
    37  }
    38  
    39  func init() {
    40  	SampleDataCmd.Flags().Int64P("seed", "s", 1, "Seed used for generating the random data (Different seeds generate different data).")
    41  	SampleDataCmd.Flags().IntP("teams", "t", 2, "The number of sample teams.")
    42  	SampleDataCmd.Flags().Int("channels-per-team", 10, "The number of sample channels per team.")
    43  	SampleDataCmd.Flags().IntP("users", "u", 15, "The number of sample users.")
    44  	SampleDataCmd.Flags().IntP("guests", "g", 1, "The number of sample guests.")
    45  	SampleDataCmd.Flags().Int("deactivated-users", 0, "The number of deactivated users.")
    46  	SampleDataCmd.Flags().Int("team-memberships", 2, "The number of sample team memberships per user.")
    47  	SampleDataCmd.Flags().Int("channel-memberships", 5, "The number of sample channel memberships per user in a team.")
    48  	SampleDataCmd.Flags().Int("posts-per-channel", 100, "The number of sample post per channel.")
    49  	SampleDataCmd.Flags().Int("direct-channels", 30, "The number of sample direct message channels.")
    50  	SampleDataCmd.Flags().Int("posts-per-direct-channel", 15, "The number of sample posts per direct message channel.")
    51  	SampleDataCmd.Flags().Int("group-channels", 15, "The number of sample group message channels.")
    52  	SampleDataCmd.Flags().Int("posts-per-group-channel", 30, "The number of sample posts per group message channel.")
    53  	SampleDataCmd.Flags().IntP("workers", "w", 2, "How many workers to run during the import.")
    54  	SampleDataCmd.Flags().String("profile-images", "", "Optional. Path to folder with images to randomly pick as user profile image.")
    55  	SampleDataCmd.Flags().StringP("bulk", "b", "", "Optional. Path to write a JSONL bulk file instead of loading into the database.")
    56  	RootCmd.AddCommand(SampleDataCmd)
    57  }
    58  
    59  func randomPastTime(seconds int) int64 {
    60  	now := time.Now()
    61  	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.FixedZone("UTC", 0))
    62  	return (today.Unix() * 1000) - int64(rand.Intn(seconds*1000))
    63  }
    64  
    65  func sortedRandomDates(size int) []int64 {
    66  	dates := make([]int64, size)
    67  	for i := 0; i < size; i++ {
    68  		dates[i] = randomPastTime(50000)
    69  	}
    70  	sort.Slice(dates, func(a, b int) bool { return dates[a] < dates[b] })
    71  	return dates
    72  }
    73  
    74  func randomEmoji() string {
    75  	emojis := []string{"+1", "-1", "heart", "blush"}
    76  	return emojis[rand.Intn(len(emojis))]
    77  }
    78  
    79  func randomReaction(users []string, parentCreateAt int64) app.ReactionImportData {
    80  	user := users[rand.Intn(len(users))]
    81  	emoji := randomEmoji()
    82  	date := parentCreateAt + int64(rand.Intn(100000))
    83  	return app.ReactionImportData{
    84  		User:      &user,
    85  		EmojiName: &emoji,
    86  		CreateAt:  &date,
    87  	}
    88  }
    89  
    90  func randomReply(users []string, parentCreateAt int64) app.ReplyImportData {
    91  	user := users[rand.Intn(len(users))]
    92  	message := randomMessage(users)
    93  	date := parentCreateAt + int64(rand.Intn(100000))
    94  	return app.ReplyImportData{
    95  		User:     &user,
    96  		Message:  &message,
    97  		CreateAt: &date,
    98  	}
    99  }
   100  
   101  func randomMessage(users []string) string {
   102  	var message string
   103  	switch rand.Intn(30) {
   104  	case 0:
   105  		mention := users[rand.Intn(len(users))]
   106  		message = "@" + mention + " " + fake.Sentence()
   107  	case 1:
   108  		switch rand.Intn(2) {
   109  		case 0:
   110  			mattermostVideos := []string{"Q4MgnxbpZas", "BFo7E9-Kc_E", "LsMLR-BHsKg", "MRmGDhlMhNA", "mUOPxT7VgWc"}
   111  			message = "https://www.youtube.com/watch?v=" + mattermostVideos[rand.Intn(len(mattermostVideos))]
   112  		case 1:
   113  			mattermostTweets := []string{"943119062334353408", "949370809528832005", "948539688171819009", "939122439115681792", "938061722027425797"}
   114  			message = "https://twitter.com/mattermosthq/status/" + mattermostTweets[rand.Intn(len(mattermostTweets))]
   115  		}
   116  	case 2:
   117  		message = ""
   118  		if rand.Intn(2) == 0 {
   119  			message += fake.Sentence()
   120  		}
   121  		for i := 0; i < rand.Intn(4)+1; i++ {
   122  			message += "\n  * " + fake.Word()
   123  		}
   124  	default:
   125  		if rand.Intn(2) == 0 {
   126  			message = fake.Sentence()
   127  		} else {
   128  			message = fake.Paragraph()
   129  		}
   130  		if rand.Intn(3) == 0 {
   131  			message += "\n" + fake.Sentence()
   132  		}
   133  		if rand.Intn(3) == 0 {
   134  			message += "\n" + fake.Sentence()
   135  		}
   136  		if rand.Intn(3) == 0 {
   137  			message += "\n" + fake.Sentence()
   138  		}
   139  	}
   140  	return message
   141  }
   142  
   143  func sampleDataCmdF(command *cobra.Command, args []string) error {
   144  	a, err := InitDBCommandContextCobra(command)
   145  	if err != nil {
   146  		return err
   147  	}
   148  	defer a.Srv().Shutdown()
   149  
   150  	seed, err := command.Flags().GetInt64("seed")
   151  	if err != nil {
   152  		return errors.New("Invalid seed parameter")
   153  	}
   154  	bulk, err := command.Flags().GetString("bulk")
   155  	if err != nil {
   156  		return errors.New("Invalid bulk parameter")
   157  	}
   158  	teams, err := command.Flags().GetInt("teams")
   159  	if err != nil || teams < 0 {
   160  		return errors.New("Invalid teams parameter")
   161  	}
   162  	channelsPerTeam, err := command.Flags().GetInt("channels-per-team")
   163  	if err != nil || channelsPerTeam < 0 {
   164  		return errors.New("Invalid channels-per-team parameter")
   165  	}
   166  	users, err := command.Flags().GetInt("users")
   167  	if err != nil || users < 0 {
   168  		return errors.New("Invalid users parameter")
   169  	}
   170  	deactivatedUsers, err := command.Flags().GetInt("deactivated-users")
   171  	if err != nil || deactivatedUsers < 0 {
   172  		return errors.New("Invalid deactivated-users parameter")
   173  	}
   174  	guests, err := command.Flags().GetInt("guests")
   175  	if err != nil || guests < 0 {
   176  		return errors.New("Invalid guests parameter")
   177  	}
   178  	teamMemberships, err := command.Flags().GetInt("team-memberships")
   179  	if err != nil || teamMemberships < 0 {
   180  		return errors.New("Invalid team-memberships parameter")
   181  	}
   182  	channelMemberships, err := command.Flags().GetInt("channel-memberships")
   183  	if err != nil || channelMemberships < 0 {
   184  		return errors.New("Invalid channel-memberships parameter")
   185  	}
   186  	postsPerChannel, err := command.Flags().GetInt("posts-per-channel")
   187  	if err != nil || postsPerChannel < 0 {
   188  		return errors.New("Invalid posts-per-channel parameter")
   189  	}
   190  	directChannels, err := command.Flags().GetInt("direct-channels")
   191  	if err != nil || directChannels < 0 {
   192  		return errors.New("Invalid direct-channels parameter")
   193  	}
   194  	postsPerDirectChannel, err := command.Flags().GetInt("posts-per-direct-channel")
   195  	if err != nil || postsPerDirectChannel < 0 {
   196  		return errors.New("Invalid posts-per-direct-channel parameter")
   197  	}
   198  	groupChannels, err := command.Flags().GetInt("group-channels")
   199  	if err != nil || groupChannels < 0 {
   200  		return errors.New("Invalid group-channels parameter")
   201  	}
   202  	postsPerGroupChannel, err := command.Flags().GetInt("posts-per-group-channel")
   203  	if err != nil || postsPerGroupChannel < 0 {
   204  		return errors.New("Invalid posts-per-group-channel parameter")
   205  	}
   206  	workers, err := command.Flags().GetInt("workers")
   207  	if err != nil {
   208  		return errors.New("Invalid workers parameter")
   209  	}
   210  	profileImagesPath, err := command.Flags().GetString("profile-images")
   211  	if err != nil {
   212  		return errors.New("Invalid profile-images parameter")
   213  	}
   214  	profileImages := []string{}
   215  	if profileImagesPath != "" {
   216  		var profileImagesStat os.FileInfo
   217  		profileImagesStat, err = os.Stat(profileImagesPath)
   218  		if os.IsNotExist(err) {
   219  			return errors.New("Profile images folder doesn't exists.")
   220  		}
   221  		if !profileImagesStat.IsDir() {
   222  			return errors.New("profile-images parameters must be a folder path.")
   223  		}
   224  		var profileImagesFiles []os.FileInfo
   225  		profileImagesFiles, err = ioutil.ReadDir(profileImagesPath)
   226  		if err != nil {
   227  			return errors.New("Invalid profile-images parameter")
   228  		}
   229  		for _, profileImage := range profileImagesFiles {
   230  			profileImages = append(profileImages, path.Join(profileImagesPath, profileImage.Name()))
   231  		}
   232  		sort.Strings(profileImages)
   233  	}
   234  
   235  	if workers < 1 {
   236  		return errors.New("You must have at least one worker.")
   237  	}
   238  	if teamMemberships > teams {
   239  		return errors.New("You can't have more team memberships than teams.")
   240  	}
   241  	if channelMemberships > channelsPerTeam {
   242  		return errors.New("You can't have more channel memberships than channels per team.")
   243  	}
   244  
   245  	if users < 6 && groupChannels > 0 {
   246  		return errors.New("You can't have group channels generation with less than 6 users. Use --group-channels 0 or increase the number of users.")
   247  	}
   248  
   249  	var bulkFile *os.File
   250  	switch bulk {
   251  	case "":
   252  		bulkFile, err = ioutil.TempFile("", ".mattermost-sample-data-")
   253  		defer os.Remove(bulkFile.Name())
   254  		if err != nil {
   255  			return errors.New("Unable to open temporary file.")
   256  		}
   257  	case "-":
   258  		bulkFile = os.Stdout
   259  	default:
   260  		bulkFile, err = os.OpenFile(bulk, os.O_RDWR|os.O_CREATE, 0755)
   261  		if err != nil {
   262  			return errors.New("Unable to write into the \"" + bulk + "\" file.")
   263  		}
   264  	}
   265  
   266  	encoder := json.NewEncoder(bulkFile)
   267  	version := 1
   268  	encoder.Encode(app.LineImportData{Type: "version", Version: &version})
   269  
   270  	fake.Seed(seed)
   271  	rand.Seed(seed)
   272  
   273  	teamsAndChannels := make(map[string][]string)
   274  	for i := 0; i < teams; i++ {
   275  		teamLine := createTeam(i)
   276  		teamsAndChannels[*teamLine.Team.Name] = []string{}
   277  		encoder.Encode(teamLine)
   278  	}
   279  
   280  	teamsList := []string{}
   281  	for teamName := range teamsAndChannels {
   282  		teamsList = append(teamsList, teamName)
   283  	}
   284  	sort.Strings(teamsList)
   285  
   286  	for _, teamName := range teamsList {
   287  		for i := 0; i < channelsPerTeam; i++ {
   288  			channelLine := createChannel(i, teamName)
   289  			teamsAndChannels[teamName] = append(teamsAndChannels[teamName], *channelLine.Channel.Name)
   290  			encoder.Encode(channelLine)
   291  		}
   292  	}
   293  
   294  	allUsers := []string{}
   295  	for i := 0; i < users; i++ {
   296  		userLine := createUser(i, teamMemberships, channelMemberships, teamsAndChannels, profileImages, "")
   297  		encoder.Encode(userLine)
   298  		allUsers = append(allUsers, *userLine.User.Username)
   299  	}
   300  	for i := 0; i < guests; i++ {
   301  		userLine := createUser(i, teamMemberships, channelMemberships, teamsAndChannels, profileImages, GuestUser)
   302  		encoder.Encode(userLine)
   303  		allUsers = append(allUsers, *userLine.User.Username)
   304  	}
   305  	for i := 0; i < deactivatedUsers; i++ {
   306  		userLine := createUser(i, teamMemberships, channelMemberships, teamsAndChannels, profileImages, DeactivatedUser)
   307  		encoder.Encode(userLine)
   308  		allUsers = append(allUsers, *userLine.User.Username)
   309  	}
   310  
   311  	for team, channels := range teamsAndChannels {
   312  		for _, channel := range channels {
   313  			dates := sortedRandomDates(postsPerChannel)
   314  
   315  			for i := 0; i < postsPerChannel; i++ {
   316  				postLine := createPost(team, channel, allUsers, dates[i])
   317  				encoder.Encode(postLine)
   318  			}
   319  		}
   320  	}
   321  
   322  	for i := 0; i < directChannels; i++ {
   323  		user1 := allUsers[rand.Intn(len(allUsers))]
   324  		user2 := allUsers[rand.Intn(len(allUsers))]
   325  		channelLine := createDirectChannel([]string{user1, user2})
   326  		encoder.Encode(channelLine)
   327  	}
   328  
   329  	for i := 0; i < directChannels; i++ {
   330  		user1 := allUsers[rand.Intn(len(allUsers))]
   331  		user2 := allUsers[rand.Intn(len(allUsers))]
   332  
   333  		dates := sortedRandomDates(postsPerDirectChannel)
   334  		for j := 0; j < postsPerDirectChannel; j++ {
   335  			postLine := createDirectPost([]string{user1, user2}, dates[j])
   336  			encoder.Encode(postLine)
   337  		}
   338  	}
   339  
   340  	for i := 0; i < groupChannels; i++ {
   341  		users := []string{}
   342  		totalUsers := 3 + rand.Intn(3)
   343  		for len(users) < totalUsers {
   344  			user := allUsers[rand.Intn(len(allUsers))]
   345  			if !utils.StringInSlice(user, users) {
   346  				users = append(users, user)
   347  			}
   348  		}
   349  		channelLine := createDirectChannel(users)
   350  		encoder.Encode(channelLine)
   351  	}
   352  
   353  	for i := 0; i < groupChannels; i++ {
   354  		users := []string{}
   355  		totalUsers := 3 + rand.Intn(3)
   356  		for len(users) < totalUsers {
   357  			user := allUsers[rand.Intn(len(allUsers))]
   358  			if !utils.StringInSlice(user, users) {
   359  				users = append(users, user)
   360  			}
   361  		}
   362  
   363  		dates := sortedRandomDates(postsPerGroupChannel)
   364  		for j := 0; j < postsPerGroupChannel; j++ {
   365  			postLine := createDirectPost(users, dates[j])
   366  			encoder.Encode(postLine)
   367  		}
   368  	}
   369  
   370  	if bulk == "" {
   371  		_, err := bulkFile.Seek(0, 0)
   372  		if err != nil {
   373  			return errors.New("Unable to read correctly the temporary file.")
   374  		}
   375  
   376  		var importErr *model.AppError
   377  		importErr, lineNumber := a.BulkImport(&request.Context{}, bulkFile, nil, false, workers)
   378  		if importErr != nil {
   379  			return fmt.Errorf("%s: %s, %s (line: %d)", importErr.Where, importErr.Message, importErr.DetailedError, lineNumber)
   380  		}
   381  		auditRec := a.MakeAuditRecord("sampleData", audit.Success)
   382  		auditRec.AddMeta("file", bulkFile.Name())
   383  		a.LogAuditRec(auditRec, nil)
   384  	} else if bulk != "-" {
   385  		err := bulkFile.Close()
   386  		if err != nil {
   387  			return errors.New("Unable to close correctly the output file")
   388  		}
   389  	}
   390  
   391  	return nil
   392  }
   393  
   394  func createUser(idx int, teamMemberships int, channelMemberships int, teamsAndChannels map[string][]string, profileImages []string, userType string) app.LineImportData {
   395  	firstName := fake.FirstName()
   396  	lastName := fake.LastName()
   397  	position := fake.JobTitle()
   398  
   399  	username := fmt.Sprintf("%s.%s", strings.ToLower(firstName), strings.ToLower(lastName))
   400  	roles := "system_user"
   401  
   402  	var password string
   403  	var email string
   404  
   405  	switch userType {
   406  	case GuestUser:
   407  		password = fmt.Sprintf("SampleGu@st-%d", idx)
   408  		email = fmt.Sprintf("guest-%d@sample.mattermost.com", idx)
   409  		roles = "system_guest"
   410  		if idx == 0 {
   411  			username = "guest"
   412  			password = "SampleGu@st1"
   413  			email = "guest@sample.mattermost.com"
   414  		}
   415  	case DeactivatedUser:
   416  		password = fmt.Sprintf("SampleDe@ctivated-%d", idx)
   417  		email = fmt.Sprintf("deactivated-%d@sample.hungknow.com", idx)
   418  	default:
   419  		password = fmt.Sprintf("SampleUs@r-%d", idx)
   420  		email = fmt.Sprintf("user-%d@sample.hungknow.com", idx)
   421  		if idx == 0 {
   422  			username = "sysadmin"
   423  			password = "Sys@dmin-sample1"
   424  			email = "sysadmin@sample.hungknow.com"
   425  		} else if idx == 1 {
   426  			username = "user-1"
   427  		}
   428  
   429  		if idx%5 == 0 {
   430  			roles = "system_admin system_user"
   431  		}
   432  	}
   433  
   434  	// The 75% of the users have custom profile image
   435  	var profileImage *string = nil
   436  	if rand.Intn(4) != 0 {
   437  		profileImageSelector := rand.Int()
   438  		if len(profileImages) > 0 {
   439  			profileImage = &profileImages[profileImageSelector%len(profileImages)]
   440  		}
   441  	}
   442  
   443  	useMilitaryTime := "false"
   444  	if idx != 0 && rand.Intn(2) == 0 {
   445  		useMilitaryTime = "true"
   446  	}
   447  
   448  	collapsePreviews := "false"
   449  	if idx != 0 && rand.Intn(2) == 0 {
   450  		collapsePreviews = "true"
   451  	}
   452  
   453  	messageDisplay := "clean"
   454  	if idx != 0 && rand.Intn(2) == 0 {
   455  		messageDisplay = "compact"
   456  	}
   457  
   458  	channelDisplayMode := "full"
   459  	if idx != 0 && rand.Intn(2) == 0 {
   460  		channelDisplayMode = "centered"
   461  	}
   462  
   463  	// Some users has nickname
   464  	nickname := ""
   465  	if rand.Intn(5) == 0 {
   466  		nickname = fake.Company()
   467  	}
   468  
   469  	// sysadmin, user-1 and user-2 users skip tutorial steps
   470  	// Other half of users also skip tutorial steps
   471  	tutorialStep := "999"
   472  	if idx > 2 {
   473  		switch rand.Intn(6) {
   474  		case 1:
   475  			tutorialStep = "1"
   476  		case 2:
   477  			tutorialStep = "2"
   478  		case 3:
   479  			tutorialStep = "3"
   480  		}
   481  	}
   482  
   483  	teams := []app.UserTeamImportData{}
   484  	possibleTeams := []string{}
   485  	for teamName := range teamsAndChannels {
   486  		possibleTeams = append(possibleTeams, teamName)
   487  	}
   488  	sort.Strings(possibleTeams)
   489  	for x := 0; x < teamMemberships; x++ {
   490  		if len(possibleTeams) == 0 {
   491  			break
   492  		}
   493  		position := rand.Intn(len(possibleTeams))
   494  		team := possibleTeams[position]
   495  		possibleTeams = append(possibleTeams[:position], possibleTeams[position+1:]...)
   496  		if teamChannels, err := teamsAndChannels[team]; err {
   497  			teams = append(teams, createTeamMembership(channelMemberships, teamChannels, &team, userType == GuestUser))
   498  		}
   499  	}
   500  
   501  	var deleteAt int64
   502  	if userType == DeactivatedUser {
   503  		deleteAt = model.GetMillis()
   504  	}
   505  
   506  	user := app.UserImportData{
   507  		ProfileImage:       profileImage,
   508  		Username:           &username,
   509  		Email:              &email,
   510  		Password:           &password,
   511  		Nickname:           &nickname,
   512  		FirstName:          &firstName,
   513  		LastName:           &lastName,
   514  		Position:           &position,
   515  		Roles:              &roles,
   516  		Teams:              &teams,
   517  		UseMilitaryTime:    &useMilitaryTime,
   518  		CollapsePreviews:   &collapsePreviews,
   519  		MessageDisplay:     &messageDisplay,
   520  		ChannelDisplayMode: &channelDisplayMode,
   521  		TutorialStep:       &tutorialStep,
   522  		DeleteAt:           &deleteAt,
   523  	}
   524  	return app.LineImportData{
   525  		Type: "user",
   526  		User: &user,
   527  	}
   528  }
   529  
   530  func createTeamMembership(numOfchannels int, teamChannels []string, teamName *string, guest bool) app.UserTeamImportData {
   531  	roles := "team_user"
   532  	if guest {
   533  		roles = "team_guest"
   534  	} else if rand.Intn(5) == 0 {
   535  		roles = "team_user team_admin"
   536  	}
   537  	channels := []app.UserChannelImportData{}
   538  	teamChannelsCopy := append([]string(nil), teamChannels...)
   539  	for x := 0; x < numOfchannels; x++ {
   540  		if len(teamChannelsCopy) == 0 {
   541  			break
   542  		}
   543  		position := rand.Intn(len(teamChannelsCopy))
   544  		channelName := teamChannelsCopy[position]
   545  		teamChannelsCopy = append(teamChannelsCopy[:position], teamChannelsCopy[position+1:]...)
   546  		channels = append(channels, createChannelMembership(channelName, guest))
   547  	}
   548  
   549  	return app.UserTeamImportData{
   550  		Name:     teamName,
   551  		Roles:    &roles,
   552  		Channels: &channels,
   553  	}
   554  }
   555  
   556  func createChannelMembership(channelName string, guest bool) app.UserChannelImportData {
   557  	roles := "channel_user"
   558  	if guest {
   559  		roles = "channel_guest"
   560  	} else if rand.Intn(5) == 0 {
   561  		roles = "channel_user channel_admin"
   562  	}
   563  	favorite := rand.Intn(5) == 0
   564  
   565  	return app.UserChannelImportData{
   566  		Name:     &channelName,
   567  		Roles:    &roles,
   568  		Favorite: &favorite,
   569  	}
   570  }
   571  
   572  func getSampleTeamName(idx int) string {
   573  	for {
   574  		name := fmt.Sprintf("%s-%d", fake.Word(), idx)
   575  		if !model.IsReservedTeamName(name) {
   576  			return name
   577  		}
   578  	}
   579  }
   580  
   581  func createTeam(idx int) app.LineImportData {
   582  	displayName := fake.Word()
   583  	name := getSampleTeamName(idx)
   584  	allowOpenInvite := rand.Intn(2) == 0
   585  
   586  	description := fake.Paragraph()
   587  	if len(description) > 255 {
   588  		description = description[0:255]
   589  	}
   590  
   591  	teamType := "O"
   592  	if rand.Intn(2) == 0 {
   593  		teamType = "I"
   594  	}
   595  
   596  	team := app.TeamImportData{
   597  		DisplayName:     &displayName,
   598  		Name:            &name,
   599  		AllowOpenInvite: &allowOpenInvite,
   600  		Description:     &description,
   601  		Type:            &teamType,
   602  	}
   603  	return app.LineImportData{
   604  		Type: "team",
   605  		Team: &team,
   606  	}
   607  }
   608  
   609  func createChannel(idx int, teamName string) app.LineImportData {
   610  	displayName := fake.Word()
   611  	name := fmt.Sprintf("%s-%d", fake.Word(), idx)
   612  	header := fake.Paragraph()
   613  	purpose := fake.Paragraph()
   614  
   615  	if len(purpose) > 250 {
   616  		purpose = purpose[0:250]
   617  	}
   618  
   619  	channelType := "P"
   620  	if rand.Intn(2) == 0 {
   621  		channelType = "O"
   622  	}
   623  
   624  	channel := app.ChannelImportData{
   625  		Team:        &teamName,
   626  		Name:        &name,
   627  		DisplayName: &displayName,
   628  		Type:        &channelType,
   629  		Header:      &header,
   630  		Purpose:     &purpose,
   631  	}
   632  	return app.LineImportData{
   633  		Type:    "channel",
   634  		Channel: &channel,
   635  	}
   636  }
   637  
   638  func createPost(team string, channel string, allUsers []string, createAt int64) app.LineImportData {
   639  	message := randomMessage(allUsers)
   640  	create_at := createAt
   641  	user := allUsers[rand.Intn(len(allUsers))]
   642  
   643  	// Some messages are flagged by an user
   644  	flagged_by := []string{}
   645  	if rand.Intn(10) == 0 {
   646  		flagged_by = append(flagged_by, allUsers[rand.Intn(len(allUsers))])
   647  	}
   648  
   649  	reactions := []app.ReactionImportData{}
   650  	if rand.Intn(10) == 0 {
   651  		for {
   652  			reactions = append(reactions, randomReaction(allUsers, create_at))
   653  			if rand.Intn(3) == 0 {
   654  				break
   655  			}
   656  		}
   657  	}
   658  
   659  	replies := []app.ReplyImportData{}
   660  	if rand.Intn(10) == 0 {
   661  		for {
   662  			replies = append(replies, randomReply(allUsers, create_at))
   663  			if rand.Intn(4) == 0 {
   664  				break
   665  			}
   666  		}
   667  	}
   668  
   669  	post := app.PostImportData{
   670  		Team:      &team,
   671  		Channel:   &channel,
   672  		User:      &user,
   673  		Message:   &message,
   674  		CreateAt:  &create_at,
   675  		FlaggedBy: &flagged_by,
   676  		Reactions: &reactions,
   677  		Replies:   &replies,
   678  	}
   679  	return app.LineImportData{
   680  		Type: "post",
   681  		Post: &post,
   682  	}
   683  }
   684  
   685  func createDirectChannel(members []string) app.LineImportData {
   686  	header := fake.Sentence()
   687  
   688  	channel := app.DirectChannelImportData{
   689  		Members: &members,
   690  		Header:  &header,
   691  	}
   692  	return app.LineImportData{
   693  		Type:          "direct_channel",
   694  		DirectChannel: &channel,
   695  	}
   696  }
   697  
   698  func createDirectPost(members []string, createAt int64) app.LineImportData {
   699  	message := randomMessage(members)
   700  	create_at := createAt
   701  	user := members[rand.Intn(len(members))]
   702  
   703  	// Some messages are flagged by an user
   704  	flagged_by := []string{}
   705  	if rand.Intn(10) == 0 {
   706  		flagged_by = append(flagged_by, members[rand.Intn(len(members))])
   707  	}
   708  
   709  	reactions := []app.ReactionImportData{}
   710  	if rand.Intn(10) == 0 {
   711  		for {
   712  			reactions = append(reactions, randomReaction(members, create_at))
   713  			if rand.Intn(3) == 0 {
   714  				break
   715  			}
   716  		}
   717  	}
   718  
   719  	replies := []app.ReplyImportData{}
   720  	if rand.Intn(10) == 0 {
   721  		for {
   722  			replies = append(replies, randomReply(members, create_at))
   723  			if rand.Intn(4) == 0 {
   724  				break
   725  			}
   726  		}
   727  	}
   728  
   729  	post := app.DirectPostImportData{
   730  		ChannelMembers: &members,
   731  		User:           &user,
   732  		Message:        &message,
   733  		CreateAt:       &create_at,
   734  		FlaggedBy:      &flagged_by,
   735  		Reactions:      &reactions,
   736  		Replies:        &replies,
   737  	}
   738  	return app.LineImportData{
   739  		Type:       "direct_post",
   740  		DirectPost: &post,
   741  	}
   742  }