github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/migration/v2_to_v3/cmd/convert_lettres/main.go (about) 1 // Script de migration des lettres des directeurs 2 // depuis la version "image inline" à la version "image lien" 3 // S'applique sur une base de données v3 4 package main 5 6 import ( 7 "bytes" 8 "database/sql" 9 "flag" 10 "strings" 11 12 "log" 13 14 rd "github.com/benoitkugler/goACVE/server/core/rawdata" 15 "github.com/benoitkugler/goACVE/logs" 16 "github.com/benoitkugler/goACVE/server/directeurs" 17 "github.com/vincent-petithory/dataurl" 18 "golang.org/x/net/html" 19 "golang.org/x/net/html/atom" 20 ) 21 22 func main() { 23 dev := flag.Bool("dev", true, "which DB to use") 24 flag.Parse() 25 26 targetHost := "acve.fr" 27 logsDB := logs.DBProd 28 if *dev { 29 targetHost = "localhost:1323" 30 logsDB = logs.DBDev 31 } 32 33 db, err := rd.ConnectDB(logsDB) 34 if err != nil { 35 log.Fatal(err) 36 } 37 defer db.Close() 38 39 tx, err := db.Begin() 40 if err != nil { 41 log.Fatal(err) 42 } 43 44 lettres, err := rd.SelectAllLettredirecteurs(tx) 45 if err != nil { 46 log.Fatal(err) 47 } 48 49 for _, lettre := range lettres { 50 // on extrait les images à importer 51 htmlNew, images := processLettre(lettre, tx, targetHost) 52 err = updateDB(lettre, htmlNew, images, tx) 53 if err != nil { 54 _ = tx.Rollback() 55 log.Fatal(err) 56 } 57 if len(images) > 0 { 58 log.Printf("imported %d images for camp %d", len(images), lettre.IdCamp) 59 } 60 } 61 62 if err = tx.Commit(); err != nil { 63 log.Fatal(err) 64 } 65 } 66 67 func processLettre(lettre rd.Lettredirecteur, tx *sql.Tx, host string) (newHtml string, images rd.Imageuploadeds) { 68 node, err := html.Parse(strings.NewReader(lettre.Html)) 69 if err != nil { 70 log.Fatal("error extracting images", err) 71 } 72 var f func(n *html.Node) 73 f = func(n *html.Node) { 74 if n.Type == html.ElementNode && n.DataAtom == atom.Img { 75 for i, attr := range n.Attr { 76 if attr.Key == "src" { // found an image 77 parsed, err := dataurl.DecodeString(attr.Val) 78 if err != nil { 79 log.Println("Skipping (camp", lettre.IdCamp, ") : image url :", attr.Val, "gives error :", err) 80 continue 81 } 82 // seule l'extension est importante 83 filename := "image." + parsed.Subtype 84 content := parsed.Data 85 lien, err := directeurs.GenerateNewImageLien(tx) 86 if err != nil { 87 log.Fatal(err) 88 } 89 90 // on sauvegarde l'image à insérer dans la base de données ... 91 images = append(images, rd.Imageuploaded{IdCamp: lettre.IdCamp, Filename: filename, Content: content, Lien: lien}) 92 93 // ... et on modifie le html en conséquence 94 imageUrl := directeurs.GetImagePublicURL(host, lien) 95 attr.Val = imageUrl 96 n.Attr[i] = attr 97 } 98 } 99 } 100 for c := n.FirstChild; c != nil; c = c.NextSibling { 101 f(c) 102 } 103 } 104 f(node) 105 if L := len(images); L > 0 { // le html a changé 106 var w bytes.Buffer 107 err := html.Render(&w, node) 108 if err != nil { 109 log.Fatal(err) 110 } 111 return w.String(), images 112 } 113 return "", nil 114 } 115 116 // ne commit ni ne rollback 117 func updateDB(lettre rd.Lettredirecteur, newHtml string, images rd.Imageuploadeds, tx *sql.Tx) error { 118 if len(images) == 0 { // rien à faire 119 return nil 120 } 121 err := rd.InsertManyImageuploadeds(tx, images...) 122 if err != nil { 123 return err 124 } 125 lettre.Html = newHtml 126 err = lettre.Delete(tx) // enlève existant 127 if err != nil { 128 return err 129 } 130 err = rd.InsertManyLettredirecteurs(tx, lettre) 131 return err 132 }