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  }