From 39aa8e2e813bdea3f46b642674d112efe3a7a00c Mon Sep 17 00:00:00 2001
From: Yevhen Odynets <6lo5jp@proton.me>
Date: Sun, 27 Sep 2026 01:12:52 +0300
Subject: [PATCH] fixed a new prescene layout
---
.idea/harvester.iml | 4 +-
cmd/srrdb/main.go | 2 +-
go.mod | 29 +++--
go.sum | 88 +++++----------
internal/releaseparser/groups/parser.go | 108 +++++++++++--------
internal/releaseparser/groups/parser_test.go | 94 ++++++++--------
pkg/repository/prescene.go | 21 ++--
7 files changed, 174 insertions(+), 172 deletions(-)
diff --git a/.idea/harvester.iml b/.idea/harvester.iml
index 9c408cc..c50f1aa 100644
--- a/.idea/harvester.iml
+++ b/.idea/harvester.iml
@@ -3,7 +3,9 @@
-
+
+
+
diff --git a/cmd/srrdb/main.go b/cmd/srrdb/main.go
index d7aef6b..6b9557a 100644
--- a/cmd/srrdb/main.go
+++ b/cmd/srrdb/main.go
@@ -49,7 +49,7 @@ func main() {
err = dbase.Select(&titles,
`SELECT title FROM theamok_mdb.external_sources
- WHERE type = 'prescene' AND releaser = ? limit 2000`, releaser)
+ WHERE type = 'prescene' AND releaser = ?`, releaser)
if err != nil {
log.Fatal(err)
}
diff --git a/go.mod b/go.mod
index 66d25d4..3684682 100644
--- a/go.mod
+++ b/go.mod
@@ -1,43 +1,42 @@
module git.kplus.net.ua/yevhen/resource-scraper
-go 1.26.2
+go 1.27
require (
github.com/davecgh/go-spew v1.1.1
- github.com/dromara/carbon/v2 v2.6.16
+ github.com/dromara/carbon/v2 v2.6.17
github.com/emersion/go-imap/v2 v2.0.0-beta.8
- github.com/go-chi/chi/v5 v5.2.5
+ github.com/go-chi/chi/v5 v5.3.2
github.com/go-chi/cors v1.2.2
github.com/go-shiori/dom v0.0.0-20230515143342-73569d674e1c
- github.com/go-sql-driver/mysql v1.9.3
+ github.com/go-sql-driver/mysql v1.10.1
github.com/iancoleman/strcase v0.3.0
github.com/jmoiron/sqlx v1.4.0
github.com/logrusorgru/aurora/v4 v4.0.0
- github.com/mewkiz/flac v1.0.13
+ github.com/mewkiz/flac v1.0.14
github.com/spf13/pflag v1.0.10
github.com/spf13/viper v1.21.0
- golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f
- golang.org/x/net v0.49.0
+ golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba
+ golang.org/x/net v0.59.0
)
require (
filippo.io/edwards25519 v1.2.0 // indirect
- github.com/andybalholm/cascadia v1.3.3 // indirect
+ github.com/andybalholm/cascadia v1.3.5 // indirect
github.com/emersion/go-message v0.18.2 // indirect
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect
- github.com/fsnotify/fsnotify v1.9.0 // indirect
+ github.com/fsnotify/fsnotify v1.10.1 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f // indirect
github.com/icza/bitio v1.1.0 // indirect
- github.com/mewkiz/pkg v0.0.0-20260331151047-10214ccde7de // indirect
+ github.com/mewkiz/pkg v0.0.0-20260703220044-4fb89b18cc87 // indirect
github.com/mewpkg/term v0.0.0-20241026122259-37a80af23985 // indirect
- github.com/pelletier/go-toml/v2 v2.2.4 // indirect
+ github.com/pelletier/go-toml/v2 v2.4.3 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
- go.yaml.in/yaml/v3 v3.0.4 // indirect
- golang.org/x/sys v0.40.0 // indirect
- golang.org/x/text v0.33.0 // indirect
- gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
+ go.yaml.in/yaml/v3 v3.0.5 // indirect
+ golang.org/x/sys v0.48.0 // indirect
+ golang.org/x/text v0.42.0 // indirect
)
diff --git a/go.sum b/go.sum
index a89feb1..cc4afb5 100644
--- a/go.sum
+++ b/go.sum
@@ -1,12 +1,12 @@
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
-github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
-github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
+github.com/andybalholm/cascadia v1.3.5 h1:RLjq12WJy58dN6eCIQrz0bAGZkztHWsEPFxP53Y7Ms8=
+github.com/andybalholm/cascadia v1.3.5/go.mod h1:BLRmbRjpEtNKieZOCCvYj4RqN+KRA41GBe/5O+G93kM=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dromara/carbon/v2 v2.6.16 h1:AbxrnW1kJhR3KHdS8G96NFmxDwPFyre+t+xSiJIUD1I=
-github.com/dromara/carbon/v2 v2.6.16/go.mod h1:NGo3reeV5vhWCYWcSqbJRZm46MEwyfYI5EJRdVFoLJo=
+github.com/dromara/carbon/v2 v2.6.17 h1:QL1LVcp5A/NQtIPbc1vrL9qIXxPNWnaDOBaFlmP1iDg=
+github.com/dromara/carbon/v2 v2.6.17/go.mod h1:NGo3reeV5vhWCYWcSqbJRZm46MEwyfYI5EJRdVFoLJo=
github.com/emersion/go-imap/v2 v2.0.0-beta.8 h1:5IXZK1E33DyeP526320J3RS7eFlCYGFgtbrfapqDPug=
github.com/emersion/go-imap/v2 v2.0.0-beta.8/go.mod h1:dhoFe2Q0PwLrMD7oZw8ODuaD0vLYPe5uj2wcOMnvh48=
github.com/emersion/go-message v0.18.2 h1:rl55SQdjd9oJcIoQNhubD2Acs1E6IzlZISRTK7x/Lpg=
@@ -15,17 +15,17 @@ github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 h1:oP4q0fw+fOSWn3
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
-github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
-github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
-github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
-github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
+github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
+github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
+github.com/go-chi/chi/v5 v5.3.2 h1:5YQkICvTCSZ25hoRsyJazN0scjzKGiu4VAUc7H1o1nY=
+github.com/go-chi/chi/v5 v5.3.2/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-shiori/dom v0.0.0-20230515143342-73569d674e1c h1:wpkoddUomPfHiOziHZixGO5ZBS73cKqVzZipfrLmO1w=
github.com/go-shiori/dom v0.0.0-20230515143342-73569d674e1c/go.mod h1:oVDCh3qjJMLVUSILBRwrm+Bc6RNXGZYtoh9xdvf1ffM=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
-github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
-github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
+github.com/go-sql-driver/mysql v1.10.1 h1:arlSnNLq6a5yxGxV7qg9lF4j0C+KwD6NbQyKr9QL6ME=
+github.com/go-sql-driver/mysql v1.10.1/go.mod h1:M+cqaI7+xxXGG9swrdeUIoPG3Y3KCkF0pZej+SK+nWk=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
@@ -50,14 +50,14 @@ github.com/logrusorgru/aurora/v4 v4.0.0 h1:sRjfPpun/63iADiSvGGjgA1cAYegEWMPCJdUp
github.com/logrusorgru/aurora/v4 v4.0.0/go.mod h1:lP0iIa2nrnT/qoFXcOZSrZQpJ1o6n2CUf/hyHi2Q4ZQ=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
-github.com/mewkiz/flac v1.0.13 h1:6wF8rRQKBFW159Daqx6Ro7K5ZnlVhHUKfS5aTsC4oXs=
-github.com/mewkiz/flac v1.0.13/go.mod h1:HfPYDA+oxjyuqMu2V+cyKcxF51KM6incpw5eZXmfA6k=
-github.com/mewkiz/pkg v0.0.0-20260331151047-10214ccde7de h1:tVseKKgTIPOo8L0gFK4qX+kqyINtWncwER/t1n2im1A=
-github.com/mewkiz/pkg v0.0.0-20260331151047-10214ccde7de/go.mod h1:omNJr4dHOKbrBeoY/idmLDFw8OIdDUUZvj3uB1cJxwA=
+github.com/mewkiz/flac v1.0.14 h1:hyRGAM8NCKznoPmIi9zz2jyO+nfmxY2ErqBnHZ+gxh4=
+github.com/mewkiz/flac v1.0.14/go.mod h1:HfPYDA+oxjyuqMu2V+cyKcxF51KM6incpw5eZXmfA6k=
+github.com/mewkiz/pkg v0.0.0-20260703220044-4fb89b18cc87 h1:fpWNLIg7nX2f+D+6ZveQ5hfkTjq5WgMBtYbz5Nb1w0Y=
+github.com/mewkiz/pkg v0.0.0-20260703220044-4fb89b18cc87/go.mod h1:wohiqwTwXA5twjDES74xIJLGjAxo3/0pHSbTXLbSDW8=
github.com/mewpkg/term v0.0.0-20241026122259-37a80af23985 h1:h8O1byDZ1uk6RUXMhj1QJU3VXFKXHDZxr4TXRPGeBa8=
github.com/mewpkg/term v0.0.0-20241026122259-37a80af23985/go.mod h1:uiPmbdUbdt1NkGApKl7htQjZ8S7XaGUAVulJUJ9v6q4=
-github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
-github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
+github.com/pelletier/go-toml/v2 v2.4.3 h1:GTRvJQutkOSftxIFD5xw9aepkYNuPWmVJpffdDPYVpY=
+github.com/pelletier/go-toml/v2 v2.4.3/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
@@ -77,81 +77,45 @@ github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
-go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
+go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
+go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
-golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
-golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
-golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
-golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
-golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
+golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba h1:Ck8QetSgk912qxWLMCKxd0in+aiyBQyDSMae6e/xmpU=
+golang.org/x/exp v0.0.0-20260908205506-85c1c2202aba/go.mod h1:50RgIsmK7OwqzTTeqcSXQW8SswW0o8fRcDxmqGluJ8E=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
-golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
-golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
-golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
-golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
-golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
+golang.org/x/net v0.59.0 h1:5zfYln+w5XCxwrnMMJPufRgNoXEaGxl0wo5GqPXyues=
+golang.org/x/net v0.59.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
-golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
-golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
+golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo=
+golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
-golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
-golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
-golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
-golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
-golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
+golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI=
+golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
-golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/internal/releaseparser/groups/parser.go b/internal/releaseparser/groups/parser.go
index a49c8ef..aa95688 100644
--- a/internal/releaseparser/groups/parser.go
+++ b/internal/releaseparser/groups/parser.go
@@ -5,8 +5,6 @@ import (
"strconv"
"strings"
- "golang.org/x/exp/slices"
-
"git.kplus.net.ua/yevhen/resource-scraper/internal/releaseparser"
)
@@ -58,31 +56,31 @@ func Parse(raw string) releaseparser.ParsedRelease {
return result
}
- // Where the dictionary-driven tail zone begins: after the resolved
- // Artist/Title core (2 tokens by default, 3 with an artist dictionary hit).
+ // Left core boundary: after the resolved Artist (2 tokens by default,
+ // 3 with an artist dictionary hit, or fixed by an override).
start := 2
// Level 1: exact-lookup override table fixes Artist/Title only;
- // the tail zone is parsed as usual below.
+ // the tail zone is parsed as usual below. The override is
+ // authoritative about the core: leftover tokens are plain unknowns,
+ // not part of the title.
if o, ok := Profile.Overrides[result.Raw]; ok {
result.Artist, result.Title = o.Artist, o.Title
start = overrideCoreLength(tokens, o)
}
- // Level 2: artist dictionary — "[0]-[1]" whitelisted as a hyphenated
- // artist shifts the core by one token.
- switch {
- case result.Artist != "":
- // An override already fixed the core — leave it alone.
- case len(tokens) >= 3 &&
- Profile.ArtistTokens[strings.ToUpper(tokens[0]+"-"+tokens[1])]:
- result.Artist = tokens[0] + "-" + tokens[1]
- result.Title = tokens[2]
- start = 3
- default:
- result.Artist = tokens[0]
- if len(tokens) > 1 {
- result.Title = tokens[1]
+ // Level 2: artist dictionary — a hyphenated artist may span ANY number
+ // of leading tokens ("Shadu-Nar-Mattaru" = 3). The LONGEST whitelisted
+ // prefix wins; the title is the token right after it. At least one
+ // title token and one tail token must remain.
+ artistDict := false
+ if result.Artist == "" {
+ for k := len(tokens) - 2; k >= 2; k-- {
+ if Profile.ArtistTokens[strings.ToUpper(strings.Join(tokens[:k], "-"))] {
+ artistDict = true
+ start = k + 1
+ break
+ }
}
}
@@ -93,8 +91,41 @@ func Parse(raw string) releaseparser.ParsedRelease {
end = len(tokens) - 2
}
+ // Right core boundary: the first dictionary-known token after the
+ // resolved artist. The boundary is contextual, but the title itself
+ // stays a single token ([1], or [2] with an artist dictionary hit).
+ // Unknown tokens inside the core region ([start .. tailStart)) are
+ // REPORTED in UnknownTokens — never eaten, never glued into the title.
+ tailStart := end
+ for i := start; i < end; i++ {
+ if isKnownToken(tokens[i]) {
+ tailStart = i
+ break
+ }
+ }
+
+ // Resolve Artist/Title from the core unless the override already did.
+ if result.Artist == "" {
+ if artistDict {
+ // The artist spans tokens [0 .. start-2]; re-join them.
+ result.Artist = strings.Join(tokens[:start-1], "-")
+ } else {
+ result.Artist = tokens[0]
+ }
+ if len(tokens) > start-1 {
+ result.Title = tokens[start-1]
+ }
+ }
+
+ // Core-region leftovers (e.g. the rest of a wildcards title after an
+ // override, or a hyphenated title fragment without an artist entry):
+ // visible in UnknownTokens for review.
+ for _, tok := range tokens[start:tailStart] {
+ result.UnknownTokens = append(result.UnknownTokens, tok)
+ }
+
// Level 3: dictionary-driven tail zone, starting after the resolved core.
- parseTailZone(start, tokens[start:end], &result)
+ parseTailZone(tokens[tailStart:end], &result)
score(&result)
return result
@@ -160,12 +191,24 @@ func catalogNumber(token string) string {
return token[1 : len(token)-1]
}
+// isKnownToken reports whether the token belongs to the tail zone: it
+// matches one of the profile dictionaries or is a parenthesized catalogue
+// number. The first such token after the core marks the right core
+// boundary.
+func isKnownToken(tok string) bool {
+ up := strings.ToUpper(tok)
+ return Profile.FormatTokens[up] || Profile.SourceTokens[up] ||
+ Profile.BitDepthTokens[up] || Profile.ResolutionTokens[up] ||
+ Profile.EditionTokens[up] || Profile.LanguageMarkers[up] ||
+ catalogNumber(tok) != ""
+}
+
// parseTailZone resolves middle-zone tokens against the dictionaries.
// The first match wins for each field; catalogue numbers are recognized
// from parenthesized tokens, and anything unrecognized is appended to
// UnknownTokens so that it can be reviewed and curated into a dictionary.
-func parseTailZone(start int, zone []string, result *releaseparser.ParsedRelease) {
- for i, tok := range zone {
+func parseTailZone(zone []string, result *releaseparser.ParsedRelease) {
+ for _, tok := range zone {
up := strings.ToUpper(tok)
switch {
case Profile.FormatTokens[up]:
@@ -197,13 +240,6 @@ func parseTailZone(start int, zone []string, result *releaseparser.ParsedRelease
default:
if cat := catalogNumber(tok); cat != "" && result.CatalogNo == "" {
result.CatalogNo = cat
- } else if hasLaterKnownToken(zone, i) {
- // suspected title continuation: the core is probably longer
- // than 2 tokens. Not eaten, not unknown — review section.
- result.TitleExtra = append(result.TitleExtra, tok)
- if !slices.Contains(result.Warnings, "suspected title continuation") {
- result.Warnings = append(result.Warnings, "suspected title continuation")
- }
} else {
result.UnknownTokens = append(result.UnknownTokens, tok)
}
@@ -220,20 +256,6 @@ func applyType(tok string, result *releaseparser.ParsedRelease) {
}
}
-// hasLaterKnownToken reports whether any token after index i in the zone
-// matches one of the profile dictionaries.
-func hasLaterKnownToken(zone []string, i int) bool {
- for _, later := range zone[i+1:] {
- up := strings.ToUpper(later)
- if Profile.FormatTokens[up] || Profile.SourceTokens[up] ||
- Profile.BitDepthTokens[up] || Profile.ResolutionTokens[up] ||
- Profile.EditionTokens[up] || Profile.LanguageMarkers[up] {
- return true
- }
- }
- return false
-}
-
// overrideCoreLength returns the number of leading tokens covered by the
// override's Artist and Title (each may span several hyphen-separated
// tokens), falling back to the default 2-token core when the raw tokens
diff --git a/internal/releaseparser/groups/parser_test.go b/internal/releaseparser/groups/parser_test.go
index 966a64a..f237dce 100644
--- a/internal/releaseparser/groups/parser_test.go
+++ b/internal/releaseparser/groups/parser_test.go
@@ -38,23 +38,20 @@ func TestParseEditionAndDemo(t *testing.T) {
func TestParseArtistWithHyphen(t *testing.T) {
// Artist сам містить дефіс, але Ultra-Violence ще не в словнику:
- // модель [0]/[1] лишається, а All_My_Life (за ним ідуть словникові
- // маркери) — suspected title continuation, не unknown.
+ // core контекстуальний — все між артистом і першим словниковим
+ // маркером (EP) є назвою, зібраною назад через "-".
r := Parse("Ultra-Violence-All_My_Life-EP-16BIT-WEB-FLAC-2026-MOONBLOOD")
- if r.Artist != "Ultra" || r.Title != "Violence" {
- t.Errorf("Artist/Title = %q/%q, want Ultra / Violence", r.Artist, r.Title)
+ if r.Artist != "Ultra" {
+ t.Errorf("Artist = %q, want Ultra", r.Artist)
+ }
+ if r.Title != "Violence" {
+ t.Errorf("Title = %q, want Violence", r.Title)
}
if r.Edition != "EP" || r.BitDepth != "16BIT" || r.Source != "WEB" || r.Year != 2026 {
t.Errorf("tail fields wrong: %+v", r)
}
- if len(r.TitleExtra) != 1 || r.TitleExtra[0] != "All_My_Life" {
- t.Errorf("TitleExtra = %v, want [All_My_Life]", r.TitleExtra)
- }
- if !contains(r.Warnings, "suspected title continuation") {
- t.Errorf("Warnings = %v, want suspected title continuation", r.Warnings)
- }
- if len(r.UnknownTokens) != 0 {
- t.Errorf("UnknownTokens = %v, want empty", r.UnknownTokens)
+ if len(r.UnknownTokens) != 1 || r.UnknownTokens[0] != "All_My_Life" {
+ t.Errorf("UnknownTokens = %v, want [All_My_Life]", r.UnknownTokens)
}
}
@@ -147,22 +144,23 @@ func TestParseUnknownTailTokenReported(t *testing.T) {
}
}
-func TestParseSuspectedTitleContinuation(t *testing.T) {
- // Невідомий токен МІЖ title-зоною і хвостом (за ним далі йдуть
- // словникові маркери) → не UnknownTokens, а TitleExtra + warning.
- r := Parse("Artist-Some_Title-SPLIT-FOO-16BIT-WEB-FLAC-2025-MOONBLOOD")
- if len(r.TitleExtra) != 1 || r.TitleExtra[0] != "FOO" {
- t.Errorf("TitleExtra = %v, want [FOO]", r.TitleExtra)
+func TestParseContextualCoreAbsorbsTitleTail(t *testing.T) {
+ // Права межа core контекстуальна (перший словниковий маркер), але
+ // невідомі токени всередині core-зони — в UnknownTokens, не з'їдаються.
+ r := Parse("Artist-Some_Title-Part_Two-Part_Three-16BIT-WEB-FLAC-2025-MOONBLOOD")
+ if r.Artist != "Artist" {
+ t.Errorf("Artist = %q, want Artist", r.Artist)
}
- if len(r.UnknownTokens) != 0 {
- t.Errorf("UnknownTokens = %v, want empty", r.UnknownTokens)
+ if r.Title != "Some_Title" {
+ t.Errorf("Title = %q, want Some_Title", r.Title)
}
- if !contains(r.Warnings, "suspected title continuation") {
- t.Errorf("Warnings = %v, want suspected title continuation", r.Warnings)
- }
- if r.Edition != "SPLIT" || r.BitDepth != "16BIT" || r.Source != "WEB" || r.Year != 2025 {
+ if r.BitDepth != "16BIT" || r.Source != "WEB" || r.Format != "FLAC" || r.Year != 2025 {
t.Errorf("tail fields wrong: %+v", r)
}
+ if len(r.UnknownTokens) != 2 || r.UnknownTokens[0] != "Part_Two" ||
+ r.UnknownTokens[1] != "Part_Three" {
+ t.Errorf("UnknownTokens = %v, want [Part_Two Part_Three]", r.UnknownTokens)
+ }
}
func TestParseCoreTokensNeverReported(t *testing.T) {
@@ -282,9 +280,8 @@ func TestParseCatalogNumberWithDotAndRoman(t *testing.T) {
}
func TestParseSplitKeepsParensAndSplitsTitles(t *testing.T) {
- // [1]=Title (фіксовано), а Evolution — не словниковий токен у середині:
- // за ним ідуть словникові маркери → suspected title continuation.
- // (SMG409) — катало, залишається каталом.
+ // Evolution — не словниковий токен у core-зоні → в UnknownTokens,
+ // не з'їдається. (SMG409) — катало, перший відомий маркер.
r := Parse("Ferosity-De-Evolution-(SMG409)-CD-FLAC-2025-86D")
if r.CatalogNo != "SMG409" {
t.Errorf("CatalogNo = %q, want SMG409", r.CatalogNo)
@@ -292,11 +289,8 @@ func TestParseSplitKeepsParensAndSplitsTitles(t *testing.T) {
if r.Artist != "Ferosity" || r.Title != "De" {
t.Errorf("Artist/Title = %q/%q, want Ferosity / De", r.Artist, r.Title)
}
- if len(r.TitleExtra) != 1 || r.TitleExtra[0] != "Evolution" {
- t.Errorf("TitleExtra = %v, want [Evolution]", r.TitleExtra)
- }
- if len(r.UnknownTokens) != 0 {
- t.Errorf("UnknownTokens = %v, want empty", r.UnknownTokens)
+ if len(r.UnknownTokens) != 1 || r.UnknownTokens[0] != "Evolution" {
+ t.Errorf("UnknownTokens = %v, want [Evolution]", r.UnknownTokens)
}
}
@@ -363,18 +357,14 @@ func TestParseCompoundEditionRecognized(t *testing.T) {
}
func TestParseMixedCaseTitleNeverReported(t *testing.T) {
- // [1]=Title (один токен). Хвіст назви (_ і Sky_Burial) — не словник,
- // але за ним ідуть словникові маркери → suspected title continuation,
- // не UnknownTokens.
+ // Хвіст назви (_Sky_Burial) — не словник, але він ДО першого маркера
+ // (катало (RTM103)) → частина назви, не UnknownTokens.
r := Parse("Enthrallment-Against_the_Will_to_Live_-_Sky_Burial-(RTM103)-CD-FLAC-2021-86D")
if r.Artist != "Enthrallment" || r.Title != "Against_the_Will_to_Live_" {
t.Errorf("Artist/Title = %q/%q", r.Artist, r.Title)
}
- if len(r.UnknownTokens) != 0 {
- t.Errorf("UnknownTokens = %v, want empty", r.UnknownTokens)
- }
- if len(r.TitleExtra) != 1 || r.TitleExtra[0] != "_Sky_Burial" {
- t.Errorf("TitleExtra = %v, want [_Sky_Burial]", r.TitleExtra)
+ if len(r.UnknownTokens) != 1 || r.UnknownTokens[0] != "_Sky_Burial" {
+ t.Errorf("UnknownTokens = %v, want [_Sky_Burial]", r.UnknownTokens)
}
if r.CatalogNo != "RTM103" {
t.Errorf("CatalogNo = %q, want RTM103", r.CatalogNo)
@@ -426,10 +416,30 @@ func TestParseArtistDictionaryCoversReleases(t *testing.T) {
}
}
+func TestParseArtistDictionaryMultiTokenArtist(t *testing.T) {
+ // artists.txt: "Shadu-Nar-Mattaru" — артист з ТРЬОХ токенів.
+ // Найдовший словниковий префікс виграє: Artist = 3 токени,
+ // Title = наступний токен, хвіст парситься як завжди.
+ r := Parse("Shadu-Nar-Mattaru-On_Pathways_Macabre-24BIT-WEB-FLAC-2023-MOONBLOOD")
+ if r.Artist != "Shadu-Nar-Mattaru" {
+ t.Errorf("Artist = %q, want Shadu-Nar-Mattaru", r.Artist)
+ }
+ if r.Title != "On_Pathways_Macabre" {
+ t.Errorf("Title = %q, want On_Pathways_Macabre", r.Title)
+ }
+ if r.BitDepth != "24BIT" || r.Source != "WEB" || r.Format != "FLAC" || r.Year != 2023 {
+ t.Errorf("tail fields wrong: %+v", r)
+ }
+ if len(r.UnknownTokens) != 0 || len(r.TitleExtra) != 0 || len(r.Warnings) != 0 {
+ t.Errorf("Unknown=%v Extra=%v Warnings=%v, want empty",
+ r.UnknownTokens, r.TitleExtra, r.Warnings)
+ }
+}
+
func TestParseOverrideWinsOverPositionalModel(t *testing.T) {
// overrides.txt (найвищий пріоритет): точний lookup по Raw
// фіксує Artist/Title; хвіст парситься як завжди.
- raw := "Milicia_Oscura-Anti-Cristo-ES-16BIT-WEB-FLAC-2024-GRAVEWAVE"
+ raw := "Milicia_Oscura-Anti-Cristo-ES-16BIT-WEB-FLAC-2013-MOONBLOOD"
r := Parse(raw)
if r.Artist != "Milicia_Oscura" {
t.Errorf("Artist = %q, want Milicia_Oscura", r.Artist)
@@ -438,7 +448,7 @@ func TestParseOverrideWinsOverPositionalModel(t *testing.T) {
t.Errorf("Title = %q, want Anti-Cristo", r.Title)
}
if r.Language != "ES" || r.BitDepth != "16BIT" || r.Source != "WEB" ||
- r.Format != "FLAC" || r.Year != 2024 || r.Group != "GRAVEWAVE" {
+ r.Format != "FLAC" || r.Year != 2013 || r.Group != "MOONBLOOD" {
t.Errorf("tail fields wrong: %+v", r)
}
if len(r.UnknownTokens) != 0 || len(r.TitleExtra) != 0 || len(r.Warnings) != 0 {
diff --git a/pkg/repository/prescene.go b/pkg/repository/prescene.go
index a728cc7..889e22b 100644
--- a/pkg/repository/prescene.go
+++ b/pkg/repository/prescene.go
@@ -85,16 +85,25 @@ func parseUrl(endpoint string, db *sqlx.DB) ([]model.ExternalSources, error) {
}
var validID = regexp.MustCompile(`-\d+\/$`)
- for i, item := range dom.QuerySelectorAll(doc, ".post.type-post.category-flac.category-music") {
+ for i, item := range dom.QuerySelectorAll(doc, "li.row") {
var es model.ExternalSources
columns := []string{"`type`", "type_id", "title", "eXsource", "releaser", "created"}
+ // TypeId тепер напряму з data-id на
, без regex по class
+ idAttr := dom.GetAttribute(item, "data-id")
+ es.TypeId, _ = strconv.Atoi(idAttr)
+
title := dom.QuerySelector(item, ".title")
if title != nil {
- anchor := dom.QuerySelector(title, "h1 > a")
+ anchor := dom.QuerySelector(title, "a")
if anchor != nil {
es.Type = constant.ScopePrescene
- es.Title = dom.GetAttribute(anchor, "title")
+
+ titleSpan := dom.QuerySelector(anchor, "span.title-start")
+ if titleSpan != nil {
+ es.Title = dom.TextContent(titleSpan)
+ }
+
if es.Title == "Auto Draft" {
slog.Info("Skipped", "title", es.Title)
continue
@@ -123,17 +132,13 @@ func parseUrl(endpoint string, db *sqlx.DB) ([]model.ExternalSources, error) {
continue
}
- localtime := dom.QuerySelector(title, "small > span.localtime")
+ localtime := dom.QuerySelector(item, "span.localtime")
if localtime != nil {
lc := dom.GetAttribute(localtime, "data-lttime")
es.Created = carbon.Parse(lc, "Europe/Kyiv")
}
}
- cls := dom.GetAttribute(item, "class")
- pattern := regexp.MustCompile(`(?s)^post-(\d+)\spost`)
- es.TypeId, _ = strconv.Atoi(pattern.FindStringSubmatch(cls)[1])
-
esModel := table.ExternalSources{Columns: columns}
entry := esModel.InsertOnDuplicate(es, db)
entries = append(entries, entry)