MM-12463 : Added capability to bulk export custom emojis (#9790)
Этот коммит содержится в:
коммит произвёл
George Goldberg
родитель
2104c6878c
Коммит
246ff89391
@@ -5,14 +5,17 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/model"
|
"github.com/mattermost/mattermost-server/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *App) BulkExport(writer io.Writer) *model.AppError {
|
func (a *App) BulkExport(writer io.Writer, file string, pathToEmojiDir string, dirNameToExportEmoji string) *model.AppError {
|
||||||
if err := a.ExportVersion(writer); err != nil {
|
if err := a.ExportVersion(writer); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -32,6 +35,9 @@ func (a *App) BulkExport(writer io.Writer) *model.AppError {
|
|||||||
if err := a.ExportAllPosts(writer); err != nil {
|
if err := a.ExportAllPosts(writer); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := a.ExportCustomEmoji(writer, file, pathToEmojiDir, dirNameToExportEmoji); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -338,3 +344,88 @@ func (a *App) BuildPostReactions(postId string) (*[]ReactionImportData, *model.A
|
|||||||
return &reactionsOfPost, nil
|
return &reactionsOfPost, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) ExportCustomEmoji(writer io.Writer, file string, pathToEmojiDir string, dirNameToExportEmoji string) *model.AppError {
|
||||||
|
pageNumber := 0
|
||||||
|
for {
|
||||||
|
customEmojiList, err := a.GetEmojiList(pageNumber, 100, model.EMOJI_SORT_BY_NAME)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(customEmojiList) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
pageNumber++
|
||||||
|
|
||||||
|
pathToDir := a.createDirForEmoji(file, dirNameToExportEmoji)
|
||||||
|
|
||||||
|
for _, emoji := range customEmojiList {
|
||||||
|
emojiImagePath := pathToEmojiDir + emoji.Id + "/image"
|
||||||
|
err := a.copyEmojiImages(emoji.Id, emojiImagePath, pathToDir)
|
||||||
|
if err != nil {
|
||||||
|
return model.NewAppError("BulkExport", "app.export.export_custom_emoji.copy_emoji_images.error", nil, "err="+err.Error(), http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath := dirNameToExportEmoji + "/" + emoji.Id + "/image"
|
||||||
|
|
||||||
|
emojiImportObject := ImportLineFromEmoji(emoji, filePath)
|
||||||
|
|
||||||
|
if err := a.ExportWriteLine(writer, emojiImportObject); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates directory named 'exported_emoji' to copy the emoji files
|
||||||
|
// Directory and the file specified by admin share the same path
|
||||||
|
func (a *App) createDirForEmoji(file string, dirName string) string {
|
||||||
|
pathToFile, _ := filepath.Abs(file)
|
||||||
|
pathSlice := strings.Split(pathToFile, "/")
|
||||||
|
if len(pathSlice) > 0 {
|
||||||
|
pathSlice = pathSlice[:len(pathSlice)-1]
|
||||||
|
}
|
||||||
|
pathToDir := strings.Join(pathSlice, "/") + "/" + dirName
|
||||||
|
|
||||||
|
if _, err := os.Stat(pathToDir); os.IsNotExist(err) {
|
||||||
|
os.Mkdir(pathToDir, os.ModePerm)
|
||||||
|
}
|
||||||
|
return pathToDir
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copies emoji files from 'data/emoji' dir to 'exported_emoji' dir
|
||||||
|
func (a *App) copyEmojiImages(emojiId string, emojiImagePath string, pathToDir string) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
fromPath, err := os.Open(emojiImagePath)
|
||||||
|
if fromPath == nil || err != nil {
|
||||||
|
return errors.New("Error reading " + emojiImagePath + "file")
|
||||||
|
}
|
||||||
|
defer fromPath.Close()
|
||||||
|
|
||||||
|
emojiDir := pathToDir + "/" + emojiId
|
||||||
|
|
||||||
|
if _, err := os.Stat(emojiDir); os.IsNotExist(err) {
|
||||||
|
os.Mkdir(emojiDir, os.ModePerm)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("Error creating directory for the emoji " + err.Error())
|
||||||
|
}
|
||||||
|
toPath, err := os.OpenFile(emojiDir+"/image", os.O_RDWR|os.O_CREATE, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("Error creating the image file " + err.Error())
|
||||||
|
}
|
||||||
|
defer toPath.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(toPath, fromPath)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("Error copying emojis " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -139,3 +139,13 @@ func ImportReactionFromPost(reaction *model.Reaction) *ReactionImportData {
|
|||||||
CreateAt: &reaction.CreateAt,
|
CreateAt: &reaction.CreateAt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ImportLineFromEmoji(emoji *model.Emoji, filePath string) *LineImportData {
|
||||||
|
return &LineImportData{
|
||||||
|
Type: "emoji",
|
||||||
|
Emoji: &EmojiImportData{
|
||||||
|
Name: &emoji.Name,
|
||||||
|
Image: &filePath,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -103,3 +104,69 @@ func TestExportUserChannels(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDirCreationForEmoji(t *testing.T) {
|
||||||
|
th := Setup().InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
|
||||||
|
pathToDir := th.App.createDirForEmoji("test.json", "exported_emoji_test")
|
||||||
|
defer os.Remove(pathToDir)
|
||||||
|
if _, err := os.Stat(pathToDir); os.IsNotExist(err) {
|
||||||
|
t.Fatal("Directory exported_emoji_test should exist")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCopyEmojiImages(t *testing.T) {
|
||||||
|
th := Setup().InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
|
||||||
|
emoji := &model.Emoji{
|
||||||
|
Id: th.BasicUser.Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating a dir named `exported_emoji_test` in the root of the repo
|
||||||
|
pathToDir := "../exported_emoji_test"
|
||||||
|
|
||||||
|
os.Mkdir(pathToDir, 0777)
|
||||||
|
defer os.RemoveAll(pathToDir)
|
||||||
|
|
||||||
|
filePath := "../data/emoji/" + emoji.Id
|
||||||
|
emojiImagePath := filePath + "/image"
|
||||||
|
|
||||||
|
var _, err = os.Stat(filePath)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
os.MkdirAll(filePath, 0777)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating a file with the name `image` to copy it to `exported_emoji_test`
|
||||||
|
os.OpenFile(filePath+"/image", os.O_RDONLY|os.O_CREATE, 0777)
|
||||||
|
defer os.RemoveAll(filePath)
|
||||||
|
|
||||||
|
copyError := th.App.copyEmojiImages(emoji.Id, emojiImagePath, pathToDir)
|
||||||
|
if copyError != nil {
|
||||||
|
t.Fatal(copyError)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(pathToDir + "/" + emoji.Id + "/image"); os.IsNotExist(err) {
|
||||||
|
t.Fatal("File should exist ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExportCustomEmoji(t *testing.T) {
|
||||||
|
th := Setup().InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
|
||||||
|
filePath := "../demo.json"
|
||||||
|
|
||||||
|
fileWriter, _ := os.Create(filePath)
|
||||||
|
defer os.Remove(filePath)
|
||||||
|
|
||||||
|
pathToEmojiDir := "../data/emoji/"
|
||||||
|
dirNameToExportEmoji := "exported_emoji_test"
|
||||||
|
|
||||||
|
err := th.App.ExportCustomEmoji(fileWriter, filePath, pathToEmojiDir, dirNameToExportEmoji)
|
||||||
|
defer os.RemoveAll("../" + dirNameToExportEmoji)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -180,7 +180,14 @@ func bulkExportCmdF(command *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
defer fileWriter.Close()
|
defer fileWriter.Close()
|
||||||
|
|
||||||
if err := a.BulkExport(fileWriter); err != nil {
|
// Path to directory of custom emoji
|
||||||
|
pathToEmojiDir := "data/emoji/"
|
||||||
|
|
||||||
|
// Name of the directory to export custom emoji
|
||||||
|
dirNameToExportEmoji := "exported_emoji"
|
||||||
|
|
||||||
|
// args[0] points to the filename/filepath passed with export bulk command
|
||||||
|
if err := a.BulkExport(fileWriter, args[0], pathToEmojiDir, dirNameToExportEmoji); err != nil {
|
||||||
CommandPrettyPrintln(err.Error())
|
CommandPrettyPrintln(err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user