mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
180 lines
4.2 KiB
Go
180 lines
4.2 KiB
Go
|
package databag
|
||
|
|
||
|
import (
|
||
|
"os"
|
||
|
"io"
|
||
|
"hash/crc32"
|
||
|
"errors"
|
||
|
"bytes"
|
||
|
"sync"
|
||
|
"regexp"
|
||
|
"databag/internal/store"
|
||
|
"os/exec"
|
||
|
"gorm.io/gorm"
|
||
|
)
|
||
|
|
||
|
var transcodeSync sync.Mutex
|
||
|
|
||
|
func transcode() {
|
||
|
|
||
|
transcodeSync.Lock()
|
||
|
defer transcodeSync.Unlock()
|
||
|
|
||
|
var assets []store.Asset
|
||
|
if err := store.DB.Preload("Account").Preload("Channel.Cards").Preload("Channel.Groups.Cards").Preload("Channel.ChannelSlot").Preload("Topic.TopicSlot").Where("status = ?", APP_ASSETWAITING).Find(&assets).Error; err != nil {
|
||
|
ErrMsg(err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// prepare script path
|
||
|
data := getStrConfigValue(CONFIG_ASSETPATH, ".")
|
||
|
script := getStrConfigValue(CONFIG_SCRIPTPATH, ".")
|
||
|
re := regexp.MustCompile("^[a-zA-Z0-9_]*$")
|
||
|
|
||
|
for _, asset := range assets {
|
||
|
|
||
|
if !re.MatchString(asset.Transform) {
|
||
|
ErrMsg(errors.New("invalid transformi"))
|
||
|
if err := UpdateAsset(&asset, APP_ASSETERROR, 0, 0); err != nil {
|
||
|
ErrMsg(err)
|
||
|
}
|
||
|
} else {
|
||
|
input := data + "/" + asset.TransformId
|
||
|
output := data + "/" + asset.AssetId
|
||
|
cmd := exec.Command(script + "/" + asset.Transform + ".sh", input, output)
|
||
|
var out bytes.Buffer
|
||
|
cmd.Stdout = &out
|
||
|
if err := cmd.Run(); err != nil {
|
||
|
LogMsg(out.String())
|
||
|
ErrMsg(err)
|
||
|
if err := UpdateAsset(&asset, APP_ASSETERROR, 0, 0); err != nil {
|
||
|
ErrMsg(err)
|
||
|
}
|
||
|
} else {
|
||
|
LogMsg(out.String())
|
||
|
crc, size, err := ScanAsset(output)
|
||
|
if err != nil {
|
||
|
ErrMsg(err)
|
||
|
if err := UpdateAsset(&asset, APP_ASSETERROR, 0, 0); err != nil {
|
||
|
ErrMsg(err)
|
||
|
}
|
||
|
} else if err := UpdateAsset(&asset, APP_ASSETREADY, crc, size); err != nil {
|
||
|
ErrMsg(err)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func isComplete(status string, asset *store.Asset) (complete bool, err error) {
|
||
|
if status == APP_ASSETREADY {
|
||
|
var assets []store.Asset
|
||
|
if err = store.DB.Where("topic_id = ?", asset.Topic.ID).Find(&assets).Error; err != nil {
|
||
|
return
|
||
|
}
|
||
|
for _, a := range asset.Topic.Assets {
|
||
|
if a.ID != asset.ID && asset.Status != APP_ASSETREADY {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
complete = true
|
||
|
return
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func UpdateAsset(asset *store.Asset, status string, crc uint32, size int64) (err error) {
|
||
|
|
||
|
act := asset.Account
|
||
|
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||
|
asset.Crc = crc
|
||
|
asset.Size = size
|
||
|
asset.Status = status
|
||
|
if res := tx.Save(asset).Error; res != nil {
|
||
|
return res
|
||
|
}
|
||
|
complete, ret := isComplete(status, asset)
|
||
|
if ret != nil {
|
||
|
return ret
|
||
|
}
|
||
|
if complete {
|
||
|
if res := tx.Model(&asset.Topic).Update("transform", APP_TRANSFORMCOMPLETE).Error; res != nil {
|
||
|
return res
|
||
|
}
|
||
|
}
|
||
|
if res := tx.Model(&asset.Topic).Update("detail_revision", act.ChannelRevision + 1).Error; res != nil {
|
||
|
return res
|
||
|
}
|
||
|
if res := tx.Model(&asset.Topic.TopicSlot).Update("revision", act.ChannelRevision + 1).Error; res != nil {
|
||
|
return res
|
||
|
}
|
||
|
if res := tx.Model(&asset.Channel.ChannelSlot).Update("revision", act.ChannelRevision + 1).Error; res != nil {
|
||
|
return res
|
||
|
}
|
||
|
if res := tx.Model(&act).Update("channel_revision", act.ChannelRevision + 1).Error; res != nil {
|
||
|
return res
|
||
|
}
|
||
|
return nil
|
||
|
})
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// determine affected contact list
|
||
|
cards := make(map[string]store.Card)
|
||
|
for _, card := range asset.Channel.Cards {
|
||
|
cards[card.Guid] = card
|
||
|
}
|
||
|
for _, group := range asset.Channel.Groups {
|
||
|
for _, card := range group.Cards {
|
||
|
cards[card.Guid] = card
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// notify
|
||
|
SetStatus(&act)
|
||
|
for _, card := range cards {
|
||
|
SetContactChannelNotification(&act, &card)
|
||
|
}
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func ScanAsset(path string) (crc uint32, size int64, err error) {
|
||
|
|
||
|
file, res := os.Open(path)
|
||
|
if res != nil {
|
||
|
err = res
|
||
|
return
|
||
|
}
|
||
|
defer file.Close()
|
||
|
|
||
|
// prepare hash
|
||
|
table := crc32.MakeTable(crc32.IEEE)
|
||
|
|
||
|
// compute has as data is saved
|
||
|
data := make([]byte, 4096)
|
||
|
for {
|
||
|
n, res := file.Read(data)
|
||
|
if res != nil {
|
||
|
if res == io.EOF {
|
||
|
break
|
||
|
}
|
||
|
err = res
|
||
|
return
|
||
|
}
|
||
|
|
||
|
crc = crc32.Update(crc, table, data[:n])
|
||
|
}
|
||
|
|
||
|
// read size
|
||
|
info, ret := file.Stat()
|
||
|
if ret != nil {
|
||
|
err = ret
|
||
|
return
|
||
|
}
|
||
|
size = info.Size()
|
||
|
return
|
||
|
}
|
||
|
|