package main import ( "fmt" "regexp" "strings" "time" "golang.org/x/text/transform" "golang.org/x/text/unicode/norm" ) // An AlbumState describe the state of an Album type AlbumState int const ( // NEW is "État neuf" state NEW AlbumState = iota // 0 // MINT is "Très bon état" state MINT // 1 // GOOD is "Bon état" state GOOD // 2 // AVERAGE is "État moyen" state AVERAGE // 3 // BAD is "Mauvais état" state BAD // 4 ) // An Album is the core object in our system // // This is basically the data we store on bdgest.com, and that we want // in our system to be retrieve from type Album struct { ID uint64 ISBN string Series string Title string Num int NumA string State AlbumState Author string Editor string Collection string SatID string LegalDeposit time.Time PrintDate time.Time PurchaseDate time.Time } var endDelim = regexp.MustCompile(` \(.*\)\z`) var wordBoundaries = regexp.MustCompile(`[^[:alnum:]]+`) var punctuation = regexp.MustCompile(`[!?\.:;,]`) func sanitizeTitleString(title string) string { // first sanitize accuented characters. isOk := func(r rune) bool { return r < 32 || r >= 127 } // The isOk filter is such that there is no need to chain to norm.NFC t := transform.Chain(norm.NFKD, transform.RemoveFunc(isOk)) // This Transformer could also trivially be applied as an io.Reader // or io.Writer filter to automatically do such filtering when reading // or writing data anywhere. title, _, _ = transform.String(t, title) //Now we remove all punctuat return strings.Trim(wordBoundaries.ReplaceAllString(punctuation.ReplaceAllString(title, ""), "-"), "-") } // GetBedethequeComURI tries to guess the URI used by bedetheque.com to reference an album, using reverse-engineered euristics func (a *Album) GetBedethequeComURI() string { // we check for determinant matches := endDelim.FindString(a.Series) series := a.Series titleMatch := false if len(matches) != 0 { series = strings.TrimSuffix(series, matches) det := strings.Trim(matches, " ()") if det[len(det)-1] != '\'' { det = det + " " } titleCompare := det + strings.ToLower(series[:1]) + series[1:] titleMatch = (titleCompare == a.Title) } else { titleMatch = (a.Series == a.Title) } series = sanitizeTitleString(series) title := sanitizeTitleString(a.Title) //first we test if we have a tome identifier tomeIdent := "" if a.Num < 0 { tomeIdent = a.NumA } else { tomeIdent = fmt.Sprintf("Tome-%d%s", a.Num, a.NumA) } if titleMatch { if len(tomeIdent) == 0 { return fmt.Sprintf("BD-%s-%d.html", series, a.ID) } return fmt.Sprintf("BD-%s-%s-%d.html", series, tomeIdent, a.ID) } if len(tomeIdent) == 0 { return fmt.Sprintf("BD-%s-%s-%d.html", series, title, a.ID) } return fmt.Sprintf("BD-%s-%s-%s-%d.html", series, tomeIdent, title, a.ID) } // An AlbumDescription is a more complete BD description // // It holds data that can be fetched from bedetheque.com type AlbumDescription struct { Album *Album HasCover bool Description string Note float64 Scenarist string Designer string Colorist string Cycle string Format string Pages int32 Created time.Time }