Use new wikitext-parser module

This commit is contained in:
DataHoarder 2022-02-20 22:42:36 +01:00
parent 4b78f093b5
commit 5db3be63f7
5 changed files with 280 additions and 488 deletions

1
go.mod
View file

@ -6,6 +6,7 @@ require (
facette.io/natsort v0.0.0-20181210072756-2cd4dd1e2dcb
git.gammaspectra.live/S.O.N.G/Hibiki v0.0.0-20220216151616-63d8894466c0
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220131114831-c08c7d9b4153
git.gammaspectra.live/S.O.N.G/wikitext-parser v0.0.0-20220220212802-e21f1e249ca9
github.com/dgraph-io/badger/v3 v3.2103.2
github.com/dhowden/tag v0.0.0-20201120070457-d52dcb253c63
github.com/ikawaha/kagome-dict/uni v1.1.3

2
go.sum
View file

@ -17,6 +17,8 @@ git.gammaspectra.live/S.O.N.G/go-pus v0.0.0-20220130003320-c9b07c6bec7a h1:LxrTp
git.gammaspectra.live/S.O.N.G/go-pus v0.0.0-20220130003320-c9b07c6bec7a/go.mod h1:vkoHSHVM9p6vAUmXAik0gvaLcIfiQYrD6bQqVpOulUk=
git.gammaspectra.live/S.O.N.G/goborator v0.0.0-20220201143845-faddd6ec920b h1:h7+SZUINAMVCY5h3E5UFT64GLaI+tJ3V758e9inPyeA=
git.gammaspectra.live/S.O.N.G/goborator v0.0.0-20220201143845-faddd6ec920b/go.mod h1:ySjuueqe5HUqvf7lWS51Cy5UP2tgJWsezOv8UIm2arA=
git.gammaspectra.live/S.O.N.G/wikitext-parser v0.0.0-20220220212802-e21f1e249ca9 h1:lIiSlBlge43zULALq20yrd4Ern1XejSRaIwWQlsc4uM=
git.gammaspectra.live/S.O.N.G/wikitext-parser v0.0.0-20220220212802-e21f1e249ca9/go.mod h1:WRXSVczbEaJc+qb8f8C9ZLi4naQl32HS0WK/eccO9Hk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=

View file

@ -4,8 +4,9 @@ import (
"encoding/json"
"fmt"
"git.gammaspectra.live/S.O.N.G/METANOIA/metadata"
"git.gammaspectra.live/S.O.N.G/METANOIA/utilities/wiki"
wikitext_parser "git.gammaspectra.live/S.O.N.G/wikitext-parser"
"github.com/oriser/regroup"
"golang.org/x/text/unicode/norm"
"io/ioutil"
"log"
"math"
@ -157,7 +158,7 @@ func (s *Source) FindQueryArguments(queryArgs string) (albums []*metadata.Album)
}
for _, r := range result.Query.Search {
album := s.GetAlbumInformation(wiki.NormalizeWikiTitle(r.Title))
album := s.GetAlbumInformation(wikitext_parser.NormalizeWikiTitle(r.Title))
if album != nil {
albums = append(albums, album)
}
@ -247,7 +248,7 @@ func (s *Source) FindAdvancedQueryArguments(queryArgs string) (albums []*metadat
}
for _, albumName := range result.Results.Text {
album := s.GetAlbumInformation(wiki.NormalizeWikiTitle(albumName))
album := s.GetAlbumInformation(wikitext_parser.NormalizeWikiTitle(albumName))
if album != nil {
albums = append(albums, album)
}
@ -276,7 +277,7 @@ func (s *Source) GetArticle(title string) ([]interface{}, error) {
return nil, err
}
return wiki.ParseWikiText(string(body)), nil
return wikitext_parser.ParseWikiText(string(body)), nil
}
func (s *Source) GetFileURL(title string) string {
@ -330,7 +331,7 @@ func (s *Source) GetFileURL(title string) string {
func (s *Source) GetSongLyrics(songName string) *metadata.Lyrics {
uri, _ := url.Parse(baseLyricsURL)
uri.Path += "lyrics/" + wiki.NormalizeWikiTitle(songName) + ".lrc"
uri.Path += "lyrics/" + wikitext_parser.NormalizeWikiTitle(songName) + ".lrc"
response, err := s.client.Request(&http.Request{
Method: "GET",
URL: uri,
@ -367,7 +368,7 @@ func (s *Source) GetSongLyrics(songName string) *metadata.Lyrics {
lyrics := &metadata.Lyrics{
Identifiers: []metadata.Name{
{Kind: "url", Name: baseURL + "歌词:" + wiki.NormalizeWikiTitle(songName)},
{Kind: "url", Name: baseURL + "歌词:" + wikitext_parser.NormalizeWikiTitle(songName)},
},
}
@ -441,6 +442,43 @@ func (s *Source) GetSongLyrics(songName string) *metadata.Lyrics {
}
func getWikiStringOptions(title string, trim bool) *wikitext_parser.WikiStringValueOptions {
opts := &wikitext_parser.WikiStringValueOptions{}
opts.Default()
opts.PageName = title
opts.StringHandler = func(value string, opt *wikitext_parser.WikiStringValueOptions) []string {
return []string{norm.NFC.String(norm.NFKD.String(value))}
}
opts.TemplateHandler = func(template *wikitext_parser.Template, opt *wikitext_parser.WikiStringValueOptions) (result []string) {
switch strings.ToUpper(template.Name) {
case "CM":
if val, ok := template.Parameters["1"]; ok && len(val) > 0 {
result = append(result, fmt.Sprintf("Comiket %s", wikitext_parser.GetWikiStringValue(val, opt)[0]))
}
case "红楼梦":
if val, ok := template.Parameters["1"]; ok && len(val) > 0 {
result = append(result, fmt.Sprintf("Touhou Kouroumu %s", wikitext_parser.GetWikiStringValue(val, opt)[0]))
}
case "例大祭":
if val, ok := template.Parameters["1"]; ok && len(val) > 0 {
result = append(result, fmt.Sprintf("Hakurei Shrine Reitaisai %s", wikitext_parser.GetWikiStringValue(val, opt)[0]))
}
case "PAGENAME", "SUBPAGENAME":
result = append(result, opt.PageName)
default:
result = append(result, template.Name)
}
return
}
opts.Trim = trim
return opts
}
func getStringValue(v []interface{}, opt *wikitext_parser.WikiStringValueOptions) []string {
return wikitext_parser.GetWikiStringValue(v, opt)
}
func (s *Source) GetAlbumInformation(title string) *metadata.Album {
article, err := s.GetArticle(title)
if err != nil {
@ -449,102 +487,10 @@ func (s *Source) GetAlbumInformation(title string) *metadata.Album {
var album *metadata.Album
normalizeStringCharacters := func(text string) string {
//TODO: use transform chain
for _, v := range [][2]string{
{"", ", "},
{"", "("},
{"", ")"},
} {
text = strings.Replace(text, v[0], v[1], -1)
}
return text
}
removeLinks := func(text string) (result string) {
index := 0
var isInternal bool
for i := 0; i < len(text); i++ {
c := text[i]
if index != 0 {
if c == ']' {
if isInternal {
segments := strings.Split(text[index:i], "|")
if len(segments) > 1 {
segments = segments[1:]
}
result += strings.Join(segments, "|")
} else {
segments := strings.Split(text[index:i], " ")
if len(segments) > 1 {
segments = segments[1:]
}
result += strings.Join(segments, " ")
}
if len(text) > i+1 && text[i+1] == ']' {
i++
}
index = 0
}
} else {
if c == '[' {
if len(text) > i+1 && text[i+1] == '[' {
i++
isInternal = true
} else {
isInternal = false
}
index = i + 1
} else {
result += text[i : i+1]
}
}
}
return
}
getStringValue := func(v []interface{}) (result []string) {
for _, value := range v {
text, ok := value.(string)
if ok {
result = append(result, normalizeStringCharacters(text))
} else {
template, ok := value.(*wiki.Template)
if ok {
switch template.Name {
case "PAGENAME":
fallthrough
case "SUBPAGENAME":
result = append(result, title)
case "CM":
result = append(result, fmt.Sprintf("Comiket %s", template.Parameters["1"][0].(string)))
case "红楼梦":
result = append(result, fmt.Sprintf("Touhou Kouroumu %s", template.Parameters["1"][0].(string)))
case "例大祭":
result = append(result, fmt.Sprintf("Hakurei Shrine Reitaisai %s", template.Parameters["1"][0].(string)))
default:
result = append(result, template.Name)
}
}
}
}
return
}
opts := getWikiStringOptions(title, true)
var staffMappings []map[string]string
listingStaff := false
var staffRE = regroup.MustCompile(`(?m)^;(?P<position>[^:]+):(?P<name>.+)$`)
var staffNameSplitRE = regroup.MustCompile(`(?P<name>[^<]+)(?P<position><br/?>|$)`)
var staffNameGroupRE = regroup.MustCompile(`(?P<position>.+)\((?P<name>.+)\)`)
var zunComposerRole = metadata.Role{
@ -555,9 +501,9 @@ func (s *Source) GetAlbumInformation(title string) *metadata.Album {
},
}
handleStaffMapping := func(discIndex int, val []interface{}, kind string, track *metadata.Track) {
handleStaffMapping := func(discIndex int, val []interface{}, kind string, track *metadata.Track, opts *wikitext_parser.WikiStringValueOptions) {
if len(staffMappings) > discIndex {
for _, e := range strings.Split(strings.Join(getStringValue(val), ","), ",") {
for _, e := range strings.Split(strings.Join(getStringValue(val, opts), ","), ",") {
entryValue := strings.TrimSpace(e)
if len(entryValue) > 0 {
@ -566,13 +512,13 @@ func (s *Source) GetAlbumInformation(title string) *metadata.Album {
if ok && groupValue != entryValue {
track.Roles = append(track.Roles, metadata.Role{
Kind: kind,
Name: []metadata.Name{{Kind: "original", Name: entryValue}, {Kind: "url", Name: baseURL + wiki.NormalizeWikiTitle(entryValue)}},
Name: []metadata.Name{{Kind: "original", Name: entryValue}, {Kind: "url", Name: baseURL + wikitext_parser.NormalizeWikiTitle(entryValue)}},
Group: groupValue,
})
} else {
track.Roles = append(track.Roles, metadata.Role{
Kind: kind,
Name: []metadata.Name{{Kind: "original", Name: entryValue}, {Kind: "url", Name: baseURL + wiki.NormalizeWikiTitle(entryValue)}},
Name: []metadata.Name{{Kind: "original", Name: entryValue}, {Kind: "url", Name: baseURL + wikitext_parser.NormalizeWikiTitle(entryValue)}},
})
}
}
@ -581,293 +527,270 @@ func (s *Source) GetAlbumInformation(title string) *metadata.Album {
}
for _, v := range article {
text, ok := v.(string)
if ok {
if text, ok := v.(string); ok {
if strings.Index(text, "== Staff ==") != -1 {
listingStaff = true
}
} else if list, ok := v.(*wikitext_parser.DescriptionList); ok {
if listingStaff {
type StaffMatch struct {
Position string `regroup:"position"`
Name string `regroup:"name"`
roleName := strings.ToLower(strings.Join(getStringValue(list.Name, opts), ""))
switch roleName {
case "total produce":
fallthrough
case "produce":
fallthrough
case "production":
roleName = "producer"
case "assistant":
roleName = "assistant"
case "illustration":
fallthrough
case "cover artwork":
roleName = "illustration"
case "mastering":
roleName = "mastering"
case "graphic design":
fallthrough
case "graphics":
fallthrough
case "design":
roleName = "design"
case "compose":
roleName = "composer"
}
m := &StaffMatch{}
rets, err := staffRE.MatchAllToTarget(normalizeStringCharacters(text), -1, m)
if err == nil {
for _, elem := range rets {
match := elem.(*StaffMatch)
for _, roleName := range strings.Split(match.Position, "/") {
roleName = strings.ToLower(strings.TrimSpace(roleName))
switch roleName {
case "total produce":
fallthrough
case "produce":
fallthrough
case "production":
roleName = "producer"
case "assistant":
roleName = "assistant"
case "illustration":
fallthrough
case "cover artwork":
roleName = "illustration"
case "mastering":
roleName = "mastering"
case "graphic design":
fallthrough
case "graphics":
fallthrough
case "design":
roleName = "design"
case "compose":
roleName = "composer"
}
rets2, err := staffNameSplitRE.MatchAllToTarget(removeLinks(strings.TrimSpace(match.Name)), -1, m)
if err == nil {
for _, elem := range rets2 {
match2 := elem.(*StaffMatch)
m3 := &StaffMatch{}
role := metadata.Role{
Kind: roleName,
Name: []metadata.Name{{Kind: "original", Name: strings.TrimSpace(match2.Name)}},
}
if staffNameGroupRE.MatchToTarget(strings.TrimSpace(match2.Name), m3) == nil {
//Is a group
role.Name = []metadata.Name{{Kind: "original", Name: strings.TrimSpace(m3.Position)}}
role.Group = strings.TrimSpace(m3.Name)
}
album.Roles = append(album.Roles, role)
}
}
}
for _, a := range strings.Split(strings.Join(getStringValue(list.Entries, opts), ""), ",") {
role := metadata.Role{
Kind: roleName,
Name: []metadata.Name{{Kind: "original", Name: strings.TrimSpace(a)}},
}
m := &struct {
Position string `regroup:"position"`
Name string `regroup:"name"`
}{}
if staffNameGroupRE.MatchToTarget(strings.TrimSpace(a), m) == nil {
//Is a group
role.Name = []metadata.Name{{Kind: "original", Name: strings.TrimSpace(m.Position)}}
role.Group = strings.TrimSpace(m.Name)
}
album.Roles = append(album.Roles, role)
}
}
} else {
template, ok := v.(*wiki.Template)
if ok {
switch template.Name {
case "专辑人员列表": //Album Person List
if album == nil {
continue
}
} else if template, ok := v.(*wikitext_parser.Template); ok {
switch template.Name {
case "专辑人员列表": //Album Person List
if album == nil {
continue
}
discIndex, _ := strconv.Atoi(strings.Join(getStringValue(template.Parameters["碟号"]), " ")) //disc number
discIndex--
discIndex, _ := strconv.Atoi(strings.Join(getStringValue(template.Parameters["碟号"], opts), " ")) //disc number
discIndex--
staffMappings = append(staffMappings, make(map[string]string))
staffMappings = append(staffMappings, make(map[string]string))
for _, val := range template.Parameters { //nested
for _, value := range getStringValue(val) {
parts := strings.Split(value, "=")
p0 := strings.TrimSpace(parts[0])
if len(parts) > 1 {
staffMappings[discIndex][p0] = strings.TrimSpace(parts[1])
} else {
staffMappings[discIndex][p0] = p0
}
for _, val := range template.Parameters { //nested
for _, value := range getStringValue(val, opts) {
parts := strings.Split(value, "=")
p0 := strings.TrimSpace(parts[0])
if len(parts) > 1 {
staffMappings[discIndex][p0] = strings.TrimSpace(parts[1])
} else {
staffMappings[discIndex][p0] = p0
}
}
case "专辑曲目列表": //Album Track List
if album == nil {
continue
}
}
case "专辑曲目列表": //Album Track List
if album == nil {
continue
}
listingStaff = false
listingStaff = false
discIndex := len(album.Discs)
discIndex := len(album.Discs)
disc := metadata.Disc{}
disc := metadata.Disc{}
for _, value := range template.Parameters["嵌套"] { //nested
tpl, ok := value.(*wiki.Template)
if ok {
track := metadata.Track{}
for k, val := range tpl.Parameters {
switch k {
case "时长": //duration
d := getStringValue(val)[0]
sub := strings.Split(d, ":")
s1, _ := strconv.ParseInt(strings.TrimLeft(sub[0], "0"), 10, 0)
if len(sub) > 2 {
//TODO
} else if len(sub) > 1 {
s2, _ := strconv.ParseInt(strings.TrimLeft(sub[1], "0"), 10, 0)
track.Duration = time.Minute*time.Duration(s1) + time.Second*time.Duration(s2)
} else {
track.Duration = time.Second * time.Duration(s1)
}
case "名称": //title
trackTitle := strings.Join(getStringValue(val), " ")
track.Name = append(track.Name, metadata.Name{
Kind: "original",
Name: trackTitle,
})
track.Lyrics = func() *metadata.Lyrics {
return s.GetSongLyrics(trackTitle)
}
case "原专辑": //original release
track.Links = append(track.Links, metadata.Link{
Kind: "original release",
Name: []metadata.Name{{Kind: "original", Name: strings.Join(getStringValue(val), " ")}},
})
case "原名称": //original release title
track.Links = append(track.Links, metadata.Link{
Kind: "original release title",
Name: []metadata.Name{{Kind: "original", Name: strings.Join(getStringValue(val), " ")}},
})
case "原曲": //original song
case "编曲": //arranger/composer
if _, ok := tpl.Parameters["原曲"]; ok {
handleStaffMapping(discIndex, val, "arranger", &track)
track.Roles = append(track.Roles, zunComposerRole) //TODO check
} else {
handleStaffMapping(discIndex, val, "composer", &track)
}
case "再编曲": //re-arranger
handleStaffMapping(discIndex, val, "remix", &track)
case "演唱": //vocals
handleStaffMapping(discIndex, val, "vocals", &track)
case "作词": //lyrics
handleStaffMapping(discIndex, val, "lyrics", &track)
for _, value := range template.Parameters["嵌套"] { //nested
if tpl, ok := value.(*wikitext_parser.Template); ok {
track := metadata.Track{}
for k, val := range tpl.Parameters {
switch k {
case "时长": //duration
d := strings.Join(getStringValue(val, opts), "")
sub := strings.Split(d, ":")
s1, _ := strconv.ParseInt(strings.TrimLeft(sub[0], "0"), 10, 0)
if len(sub) > 2 {
//TODO
} else if len(sub) > 1 {
s2, _ := strconv.ParseInt(strings.TrimLeft(sub[1], "0"), 10, 0)
track.Duration = time.Minute*time.Duration(s1) + time.Second*time.Duration(s2)
} else {
track.Duration = time.Second * time.Duration(s1)
}
case "名称": //title
trackTitle := strings.Join(getStringValue(val, opts), " ")
track.Name = append(track.Name, metadata.Name{
Kind: "original",
Name: trackTitle,
})
track.Lyrics = func() *metadata.Lyrics {
return s.GetSongLyrics(trackTitle)
}
case "原专辑": //original release
track.Links = append(track.Links, metadata.Link{
Kind: "original release",
Name: []metadata.Name{{Kind: "original", Name: strings.Join(getStringValue(val, opts), " ")}},
})
case "原名称": //original release title
track.Links = append(track.Links, metadata.Link{
Kind: "original release title",
Name: []metadata.Name{{Kind: "original", Name: strings.Join(getStringValue(val, opts), " ")}},
})
case "原曲": //original song
case "编曲": //arranger/composer
if _, ok := tpl.Parameters["原曲"]; ok {
handleStaffMapping(discIndex, val, "arranger", &track, opts)
track.Roles = append(track.Roles, zunComposerRole) //TODO check
} else {
handleStaffMapping(discIndex, val, "composer", &track, opts)
}
case "再编曲": //re-arranger
handleStaffMapping(discIndex, val, "remix", &track, opts)
case "演唱": //vocals
handleStaffMapping(discIndex, val, "vocals", &track, opts)
case "作词": //lyrics
handleStaffMapping(discIndex, val, "lyrics", &track, opts)
}
disc.Tracks = append(disc.Tracks, track)
}
disc.Tracks = append(disc.Tracks, track)
}
}
album.Discs = append(album.Discs, disc)
album.Discs = append(album.Discs, disc)
case "同人专辑信息": //Doujin Album Information
album = &metadata.Album{
License: s.GetLicense(),
SourceUniqueIdentifier: baseURL + title,
Identifiers: []metadata.Name{
{
Kind: "url",
Name: baseURL + title,
},
case "同人专辑信息": //Doujin Album Information
album = &metadata.Album{
License: s.GetLicense(),
SourceUniqueIdentifier: baseURL + title,
Identifiers: []metadata.Name{
{
Kind: "url",
Name: baseURL + title,
},
}
},
}
album.Identifiers = append(album.Identifiers)
album.Identifiers = append(album.Identifiers)
for k, val := range template.Parameters {
for k, val := range template.Parameters {
switch k {
case "封面": //cover: jpg
fileName := strings.Join(getStringValue(val), "")
if strings.Index(fileName, ".") == -1 {
fileName = title + "封面." + fileName
}
f := s.GetFileURL(fileName)
if len(f) > 0 {
album.Art = append(album.Art, metadata.Name{
Kind: "front",
Name: s.GetFileURL(fileName),
})
}
case "展会": //release
for _, value := range val {
tpl, ok := value.(*wiki.Template)
if ok {
switch tpl.Name {
case "CM":
album.Links = append(album.Links, metadata.Link{
Kind: "release",
Name: []metadata.Name{
{Kind: "name", Name: fmt.Sprintf("Comiket %s", tpl.Parameters["1"][0].(string))},
},
})
case "红楼梦":
album.Links = append(album.Links, metadata.Link{
Kind: "release",
Name: []metadata.Name{
{Kind: "name", Name: fmt.Sprintf("Touhou Kouroumu %s", tpl.Parameters["1"][0].(string))},
},
})
case "例大祭":
album.Links = append(album.Links, metadata.Link{
Kind: "release",
Name: []metadata.Name{
{Kind: "name", Name: fmt.Sprintf("Hakurei Shrine Reitaisai %s", tpl.Parameters["1"][0].(string))},
},
})
}
break
}
}
case "名称": //name
album.Name = append(album.Name, metadata.Name{
Kind: "original",
Name: strings.Join(getStringValue(val), " "),
})
case "制作方": //produced by
for _, producer := range strings.Split(strings.Join(getStringValue(val), ","), ",") {
album.Roles = append(album.Roles, metadata.Role{
Kind: "producer",
Name: []metadata.Name{{Kind: "original", Name: producer}, {Kind: "url", Name: baseURL + wiki.NormalizeWikiTitle(producer)}},
})
}
case "发行方": //issuer
for _, issuer := range strings.Split(strings.Join(getStringValue(val), ","), ",") {
album.Roles = append(album.Roles, metadata.Role{
Kind: "issuer",
Name: []metadata.Name{{Kind: "original", Name: issuer}, {Kind: "url", Name: baseURL + wiki.NormalizeWikiTitle(issuer)}},
})
}
case "编号": //catalog number
for _, catalog := range strings.Split(strings.Join(getStringValue(val), "+"), "+") {
album.Identifiers = append(album.Identifiers, metadata.Name{
Kind: "catalog",
Name: catalog,
})
}
case "风格类型": //style
for _, style := range strings.Split(strings.Join(getStringValue(val), ","), ",") {
switch strings.ToLower(style) {
default:
album.Tags = append(album.Tags, metadata.Name{
Kind: "genre",
Name: strings.ToLower(style), //TODO: normalize
})
}
}
case "官网页面": //official page
album.Links = append(album.Links, metadata.Link{
Kind: "official",
Name: []metadata.Name{{Kind: "url", Name: strings.Join(getStringValue(val), " ")}},
switch k {
case "封面": //cover: jpg
fileName := strings.Join(getStringValue(val, opts), "")
if strings.Index(fileName, ".") == -1 {
fileName = title + "封面." + fileName
}
f := s.GetFileURL(fileName)
if len(f) > 0 {
album.Art = append(album.Art, metadata.Name{
Kind: "front",
Name: s.GetFileURL(fileName),
})
}
case "展会": //release
for _, value := range val {
tpl, ok := value.(*wikitext_parser.Template)
if ok {
//TODO
switch tpl.Name {
case "CM":
album.Links = append(album.Links, metadata.Link{
Kind: "release",
Name: []metadata.Name{
{Kind: "name", Name: fmt.Sprintf("Comiket %s", tpl.Parameters["1"][0].(string))},
},
})
case "红楼梦":
album.Links = append(album.Links, metadata.Link{
Kind: "release",
Name: []metadata.Name{
{Kind: "name", Name: fmt.Sprintf("Touhou Kouroumu %s", tpl.Parameters["1"][0].(string))},
},
})
case "例大祭":
album.Links = append(album.Links, metadata.Link{
Kind: "release",
Name: []metadata.Name{
{Kind: "name", Name: fmt.Sprintf("Hakurei Shrine Reitaisai %s", tpl.Parameters["1"][0].(string))},
},
})
}
break
}
}
case "名称": //name
album.Name = append(album.Name, metadata.Name{
Kind: "original",
Name: strings.Join(getStringValue(val, opts), " "),
})
case "制作方": //produced by
for _, producer := range strings.Split(strings.Join(getStringValue(val, opts), ","), ",") {
album.Roles = append(album.Roles, metadata.Role{
Kind: "producer",
Name: []metadata.Name{{Kind: "original", Name: producer}, {Kind: "url", Name: baseURL + wikitext_parser.NormalizeWikiTitle(producer)}},
})
}
case "发行方": //issuer
for _, issuer := range strings.Split(strings.Join(getStringValue(val, opts), ","), ",") {
album.Roles = append(album.Roles, metadata.Role{
Kind: "issuer",
Name: []metadata.Name{{Kind: "original", Name: issuer}, {Kind: "url", Name: baseURL + wikitext_parser.NormalizeWikiTitle(issuer)}},
})
}
case "编号": //catalog number
for _, catalog := range strings.Split(strings.Join(getStringValue(val, opts), "+"), "+") {
album.Identifiers = append(album.Identifiers, metadata.Name{
Kind: "catalog",
Name: catalog,
})
}
case "风格类型": //style
for _, style := range strings.Split(strings.Join(getStringValue(val, opts), ","), ",") {
switch strings.ToLower(style) {
default:
album.Tags = append(album.Tags, metadata.Name{
Kind: "genre",
Name: strings.ToLower(style), //TODO: normalize
})
}
}
case "官网页面": //official page
album.Links = append(album.Links, metadata.Link{
Kind: "official",
Name: []metadata.Name{{Kind: "url", Name: strings.Join(getStringValue(val, opts), " ")}},
})
}
}
} else {
//unknown value
continue
}
} else {
continue
}
}

View file

@ -1,108 +0,0 @@
package wiki
import "strings"
func NormalizeWikiTitle(title string) string {
//TODO
return strings.Replace(title, " ", "_", -1)
}
//ParseWikiText small WikiText parser that extracts text, Templates, and its arguments/parameters
func ParseWikiText(text string) (result []interface{}) {
index := 0
for index < len(text) {
templateIndex := strings.Index(text[index:], "{{")
if templateIndex == -1 {
t := strings.TrimSpace(text[index:])
if len(t) > 0 {
result = append(result, t)
}
break
} else {
t := strings.TrimSpace(text[index : index+templateIndex])
if len(t) > 0 {
result = append(result, t)
}
var tpl *Template
index, tpl = ParseTemplate(text, index+templateIndex+2, 0)
if tpl != nil {
result = append(result, tpl)
}
}
}
return
}
func ParseTemplate(text string, index int, depth int) (i int, template *Template) {
var c byte
lastToken := index
var key string
addValue := func() int {
if lastToken < len(text) && i-lastToken > 0 {
t := strings.TrimSpace(text[lastToken:i])
if len(t) > 0 {
if template == nil {
template = NewTemplate(t)
} else {
if key == "" {
template.AddParameterUnkeyed(t)
} else {
template.AddParameter(key, t)
}
}
}
return len(t)
}
return 0
}
addKey := func() {
if lastToken < len(text) && i-lastToken > 0 {
t := strings.TrimSpace(text[lastToken:i])
if len(t) > 0 {
key = t
}
}
}
for i = index; i < len(text); i++ {
c = text[i]
if c == '}' && i < len(text)-1 && text[i+1] == '}' {
addValue()
i += 2
break
} else if c == '{' && i < len(text)-1 && text[i+1] == '{' {
addValue()
var tpl *Template
i, tpl = ParseTemplate(text, i+2, depth+1)
if tpl != nil {
if key == "" {
template.AddParameterUnkeyed(tpl)
} else {
template.AddParameter(key, tpl)
}
}
lastToken = i
} else if c == '|' {
addValue()
lastToken = i + 1
key = ""
} else if c == '\n' {
addValue()
lastToken = i + 1
} else if c == '=' {
if key == "" {
addKey()
lastToken = i + 1
}
}
}
return
}

View file

@ -1,26 +0,0 @@
package wiki
import "fmt"
type Template struct {
Name string
Parameters map[string][]interface{}
}
func NewTemplate(name string) *Template {
return &Template{
Name: name,
Parameters: make(map[string][]interface{}),
}
}
func (t *Template) AddParameterUnkeyed(value interface{}) {
t.Parameters[fmt.Sprintf("%d", len(t.Parameters))] = []interface{}{value}
}
func (t *Template) AddParameter(key string, value interface{}) {
if _, ok := t.Parameters[key]; !ok {
t.Parameters[key] = make([]interface{}, 0, 1)
}
t.Parameters[key] = append(t.Parameters[key], value)
}