mirror of
https://codeberg.org/scip/kleingebaeck.git
synced 2025-12-17 20:41:01 +01:00
Compare commits
2 Commits
fix/gocrit
...
fix/crash-
| Author | SHA1 | Date | |
|---|---|---|---|
| b464a1bfaa | |||
| e838f71781 |
10
config.go
10
config.go
@@ -34,7 +34,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VERSION string = "0.3.3"
|
VERSION string = "0.3.4"
|
||||||
Baseuri string = "https://www.kleinanzeigen.de"
|
Baseuri string = "https://www.kleinanzeigen.de"
|
||||||
Listuri string = "/s-bestandsliste.html"
|
Listuri string = "/s-bestandsliste.html"
|
||||||
Defaultdir string = "."
|
Defaultdir string = "."
|
||||||
@@ -52,6 +52,8 @@ const (
|
|||||||
|
|
||||||
DefaultAdNameTemplate string = "{{.Slug}}"
|
DefaultAdNameTemplate string = "{{.Slug}}"
|
||||||
|
|
||||||
|
DefaultOutdirTemplate string = "."
|
||||||
|
|
||||||
// for image download throttling
|
// for image download throttling
|
||||||
MinThrottle int = 2
|
MinThrottle int = 2
|
||||||
MaxThrottle int = 20
|
MaxThrottle int = 20
|
||||||
@@ -65,6 +67,8 @@ const (
|
|||||||
WIN string = "windows"
|
WIN string = "windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var DirsVisited map[string]int
|
||||||
|
|
||||||
const Usage string = `This is kleingebaeck, the kleinanzeigen.de backup tool.
|
const Usage string = `This is kleingebaeck, the kleinanzeigen.de backup tool.
|
||||||
|
|
||||||
Usage: kleingebaeck [-dvVhmoclu] [<ad-listing-url>,...]
|
Usage: kleingebaeck [-dvVhmoclu] [<ad-listing-url>,...]
|
||||||
@@ -77,7 +81,7 @@ Options:
|
|||||||
-l --limit <num> Limit the ads to download to <num>, default: load all.
|
-l --limit <num> Limit the ads to download to <num>, default: load all.
|
||||||
-c --config <file> Use config file <file> (default: ~/.kleingebaeck).
|
-c --config <file> Use config file <file> (default: ~/.kleingebaeck).
|
||||||
--ignoreerrors Ignore HTTP errors, may lead to incomplete ad backup.
|
--ignoreerrors Ignore HTTP errors, may lead to incomplete ad backup.
|
||||||
-f --force Download images even if they already exist.
|
-f --force Overwrite images and ads even if the already exist.
|
||||||
-m --manual Show manual.
|
-m --manual Show manual.
|
||||||
-h --help Show usage.
|
-h --help Show usage.
|
||||||
-V --version Show program version.
|
-V --version Show program version.
|
||||||
@@ -126,7 +130,7 @@ func InitConfig(output io.Writer) (*Config, error) {
|
|||||||
// Load default values using the confmap provider.
|
// Load default values using the confmap provider.
|
||||||
if err := kloader.Load(confmap.Provider(map[string]interface{}{
|
if err := kloader.Load(confmap.Provider(map[string]interface{}{
|
||||||
"template": template,
|
"template": template,
|
||||||
"outdir": ".",
|
"outdir": DefaultOutdirTemplate,
|
||||||
"loglevel": "notice",
|
"loglevel": "notice",
|
||||||
"userid": 0,
|
"userid": 0,
|
||||||
"adnametemplate": DefaultAdNameTemplate,
|
"adnametemplate": DefaultAdNameTemplate,
|
||||||
|
|||||||
4
go.mod
4
go.mod
@@ -14,7 +14,7 @@ require (
|
|||||||
github.com/lmittmann/tint v1.0.4
|
github.com/lmittmann/tint v1.0.4
|
||||||
github.com/mattn/go-isatty v0.0.20
|
github.com/mattn/go-isatty v0.0.20
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/tlinden/yadu v0.1.1
|
github.com/tlinden/yadu v0.1.2
|
||||||
golang.org/x/sync v0.5.0
|
golang.org/x/sync v0.5.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ require (
|
|||||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
|
||||||
golang.org/x/sys v0.14.0 // indirect
|
golang.org/x/sys v0.17.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -66,6 +66,8 @@ github.com/tlinden/yadu v0.1.0 h1:qtCi1jxg392qVRLFyrJ2LYu6/PiKSp1LT02EX+mNLME=
|
|||||||
github.com/tlinden/yadu v0.1.0/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA=
|
github.com/tlinden/yadu v0.1.0/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA=
|
||||||
github.com/tlinden/yadu v0.1.1 h1:116oEUy9b4PcMF5wLL2dCFA/sn/praYutOnao07MROw=
|
github.com/tlinden/yadu v0.1.1 h1:116oEUy9b4PcMF5wLL2dCFA/sn/praYutOnao07MROw=
|
||||||
github.com/tlinden/yadu v0.1.1/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA=
|
github.com/tlinden/yadu v0.1.1/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA=
|
||||||
|
github.com/tlinden/yadu v0.1.2 h1:TYYVnUJwziRJ9YPbIbRf9ikmDw0Q8Ifixm+J/kBQFh8=
|
||||||
|
github.com/tlinden/yadu v0.1.2/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -81,6 +83,8 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||||
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
@@ -133,7 +133,7 @@
|
|||||||
.\" ========================================================================
|
.\" ========================================================================
|
||||||
.\"
|
.\"
|
||||||
.IX Title "KLEINGEBAECK 1"
|
.IX Title "KLEINGEBAECK 1"
|
||||||
.TH KLEINGEBAECK 1 "2024-01-25" "1" "User Commands"
|
.TH KLEINGEBAECK 1 "2024-02-10" "1" "User Commands"
|
||||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||||
.\" way too many mistakes in technical documents.
|
.\" way too many mistakes in technical documents.
|
||||||
.if n .ad l
|
.if n .ad l
|
||||||
@@ -152,7 +152,7 @@ kleingebaeck \- kleinanzeigen.de backup tool
|
|||||||
\& \-l \-\-limit <num> Limit the ads to download to <num>, default: load all.
|
\& \-l \-\-limit <num> Limit the ads to download to <num>, default: load all.
|
||||||
\& \-c \-\-config <file> Use config file <file> (default: ~/.kleingebaeck).
|
\& \-c \-\-config <file> Use config file <file> (default: ~/.kleingebaeck).
|
||||||
\& \-\-ignoreerrors Ignore HTTP errors, may lead to incomplete ad backup.
|
\& \-\-ignoreerrors Ignore HTTP errors, may lead to incomplete ad backup.
|
||||||
\& \-f \-\-force Download images even if they already exist.
|
\& \-f \-\-force Overwrite images and ads even if the already exist.
|
||||||
\& \-m \-\-manual Show manual.
|
\& \-m \-\-manual Show manual.
|
||||||
\& \-h \-\-help Show usage.
|
\& \-h \-\-help Show usage.
|
||||||
\& \-V \-\-version Show program version.
|
\& \-V \-\-version Show program version.
|
||||||
@@ -195,7 +195,7 @@ Be careful if you want to change the template. The variable is a
|
|||||||
multiline string surrounded by three double quotes. You can left out
|
multiline string surrounded by three double quotes. You can left out
|
||||||
certain fields and use any formatting you like. Refer to
|
certain fields and use any formatting you like. Refer to
|
||||||
<https://pkg.go.dev/text/template> for details how to write a
|
<https://pkg.go.dev/text/template> for details how to write a
|
||||||
template.
|
template. Also read the \s-1TEMPLATES\s0 section below.
|
||||||
.PP
|
.PP
|
||||||
If you're on windows and want to customize the output directory, put
|
If you're on windows and want to customize the output directory, put
|
||||||
it into single quotes to avoid the backslashes interpreted as escape
|
it into single quotes to avoid the backslashes interpreted as escape
|
||||||
@@ -204,6 +204,94 @@ chars like this:
|
|||||||
.Vb 1
|
.Vb 1
|
||||||
\& outdir = \*(AqC:\eData\eAds\*(Aq
|
\& outdir = \*(AqC:\eData\eAds\*(Aq
|
||||||
.Ve
|
.Ve
|
||||||
|
.SH "TEMPLATES"
|
||||||
|
.IX Header "TEMPLATES"
|
||||||
|
Various parts of the configuration can be modified using templates:
|
||||||
|
the output directory, the ad directory and the ad listing itself.
|
||||||
|
.SS "\s-1OUTPUT DIR TEMPLATE\s0"
|
||||||
|
.IX Subsection "OUTPUT DIR TEMPLATE"
|
||||||
|
The config varialbe \f(CW\*(C`outdir\*(C'\fR or the command line parameter \f(CW\*(C`\-o\*(C'\fR take a
|
||||||
|
template which may contain:
|
||||||
|
.ie n .IP """{{.Year}}""" 4
|
||||||
|
.el .IP "\f(CW{{.Year}}\fR" 4
|
||||||
|
.IX Item "{{.Year}}"
|
||||||
|
.PD 0
|
||||||
|
.ie n .IP """{{.Month}}""" 4
|
||||||
|
.el .IP "\f(CW{{.Month}}\fR" 4
|
||||||
|
.IX Item "{{.Month}}"
|
||||||
|
.ie n .IP """{{.Day}}""" 4
|
||||||
|
.el .IP "\f(CW{{.Day}}\fR" 4
|
||||||
|
.IX Item "{{.Day}}"
|
||||||
|
.PD
|
||||||
|
.PP
|
||||||
|
That way you can create a new output directory for every backup
|
||||||
|
run. For example:
|
||||||
|
.PP
|
||||||
|
.Vb 1
|
||||||
|
\& outdir = "/home/backups/ads\-{{.Year}}\-{{.Month}}\-{{.Day}}"
|
||||||
|
.Ve
|
||||||
|
.PP
|
||||||
|
Or using the command line flag:
|
||||||
|
.PP
|
||||||
|
.Vb 1
|
||||||
|
\& \-o "/home/backups/ads\-{{.Year}}\-{{.Month}}\-{{.Day}}"
|
||||||
|
.Ve
|
||||||
|
.PP
|
||||||
|
The default value is \f(CW\*(C`.\*(C'\fR \- the current directory.
|
||||||
|
.SS "\s-1AD DIRECTORY TEMPLATE\s0"
|
||||||
|
.IX Subsection "AD DIRECTORY TEMPLATE"
|
||||||
|
The ad directory name can be modified using the following ad values:
|
||||||
|
.IP "{{.Price}}" 4
|
||||||
|
.IX Item "{{.Price}}"
|
||||||
|
.PD 0
|
||||||
|
.IP "{{.ID}}" 4
|
||||||
|
.IX Item "{{.ID}}"
|
||||||
|
.IP "{{.Category}}" 4
|
||||||
|
.IX Item "{{.Category}}"
|
||||||
|
.IP "{{.Condition}}" 4
|
||||||
|
.IX Item "{{.Condition}}"
|
||||||
|
.IP "{{.Created}}" 4
|
||||||
|
.IX Item "{{.Created}}"
|
||||||
|
.IP "{{.Slug}}" 4
|
||||||
|
.IX Item "{{.Slug}}"
|
||||||
|
.IP "{{.Text}}" 4
|
||||||
|
.IX Item "{{.Text}}"
|
||||||
|
.PD
|
||||||
|
.PP
|
||||||
|
It can only be configured in the config file. By default only
|
||||||
|
\&\f(CW\*(C`{{.Slug}}\*(C'\fR is being used, this is the title of the ad in url format.
|
||||||
|
.SS "\s-1AD TEMPLATE\s0"
|
||||||
|
.IX Subsection "AD TEMPLATE"
|
||||||
|
The ad listing itself can be modified as well, using the same
|
||||||
|
variables as the ad name template above.
|
||||||
|
.PP
|
||||||
|
This is the default template:
|
||||||
|
.PP
|
||||||
|
.Vb 7
|
||||||
|
\& Title: {{.Title}}
|
||||||
|
\& Price: {{.Price}}
|
||||||
|
\& Id: {{.ID}}
|
||||||
|
\& Category: {{.Category}}
|
||||||
|
\& Condition: {{.Condition}}
|
||||||
|
\& Created: {{.Created}}
|
||||||
|
\& Expire: {{.Expire}}
|
||||||
|
\&
|
||||||
|
\& {{.Text}}
|
||||||
|
.Ve
|
||||||
|
.PP
|
||||||
|
The config parameter to modify is \f(CW\*(C`template\*(C'\fR. See example.conf in the
|
||||||
|
source repository. Please take care, since this is a multiline
|
||||||
|
string. This is how it shall look if you modify it:
|
||||||
|
.PP
|
||||||
|
.Vb 2
|
||||||
|
\& template="""
|
||||||
|
\& Title: {{.Title}}
|
||||||
|
\&
|
||||||
|
\& {{.Text}}
|
||||||
|
\& """
|
||||||
|
.Ve
|
||||||
|
.PP
|
||||||
|
That is, the content between the two \f(CW"""\fR chars is the template.
|
||||||
.SH "SETUP"
|
.SH "SETUP"
|
||||||
.IX Header "SETUP"
|
.IX Header "SETUP"
|
||||||
To setup the tool, you need to lookup your userid on
|
To setup the tool, you need to lookup your userid on
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ SYNOPSYS
|
|||||||
-l --limit <num> Limit the ads to download to <num>, default: load all.
|
-l --limit <num> Limit the ads to download to <num>, default: load all.
|
||||||
-c --config <file> Use config file <file> (default: ~/.kleingebaeck).
|
-c --config <file> Use config file <file> (default: ~/.kleingebaeck).
|
||||||
--ignoreerrors Ignore HTTP errors, may lead to incomplete ad backup.
|
--ignoreerrors Ignore HTTP errors, may lead to incomplete ad backup.
|
||||||
-f --force Download images even if they already exist.
|
-f --force Overwrite images and ads even if the already exist.
|
||||||
-m --manual Show manual.
|
-m --manual Show manual.
|
||||||
-h --help Show usage.
|
-h --help Show usage.
|
||||||
-V --version Show program version.
|
-V --version Show program version.
|
||||||
@@ -55,6 +55,7 @@ CONFIGURATION
|
|||||||
multiline string surrounded by three double quotes. You can left out
|
multiline string surrounded by three double quotes. You can left out
|
||||||
certain fields and use any formatting you like. Refer to
|
certain fields and use any formatting you like. Refer to
|
||||||
<https://pkg.go.dev/text/template> for details how to write a template.
|
<https://pkg.go.dev/text/template> for details how to write a template.
|
||||||
|
Also read the TEMPLATES section below.
|
||||||
|
|
||||||
If you're on windows and want to customize the output directory, put it
|
If you're on windows and want to customize the output directory, put it
|
||||||
into single quotes to avoid the backslashes interpreted as escape chars
|
into single quotes to avoid the backslashes interpreted as escape chars
|
||||||
@@ -62,6 +63,71 @@ CONFIGURATION
|
|||||||
|
|
||||||
outdir = 'C:\Data\Ads'
|
outdir = 'C:\Data\Ads'
|
||||||
|
|
||||||
|
TEMPLATES
|
||||||
|
Various parts of the configuration can be modified using templates: the
|
||||||
|
output directory, the ad directory and the ad listing itself.
|
||||||
|
|
||||||
|
OUTPUT DIR TEMPLATE
|
||||||
|
The config varialbe "outdir" or the command line parameter "-o" take a
|
||||||
|
template which may contain:
|
||||||
|
|
||||||
|
"{{.Year}}"
|
||||||
|
"{{.Month}}"
|
||||||
|
"{{.Day}}"
|
||||||
|
|
||||||
|
That way you can create a new output directory for every backup run. For
|
||||||
|
example:
|
||||||
|
|
||||||
|
outdir = "/home/backups/ads-{{.Year}}-{{.Month}}-{{.Day}}"
|
||||||
|
|
||||||
|
Or using the command line flag:
|
||||||
|
|
||||||
|
-o "/home/backups/ads-{{.Year}}-{{.Month}}-{{.Day}}"
|
||||||
|
|
||||||
|
The default value is "." - the current directory.
|
||||||
|
|
||||||
|
AD DIRECTORY TEMPLATE
|
||||||
|
The ad directory name can be modified using the following ad values:
|
||||||
|
|
||||||
|
{{.Price}}
|
||||||
|
{{.ID}}
|
||||||
|
{{.Category}}
|
||||||
|
{{.Condition}}
|
||||||
|
{{.Created}}
|
||||||
|
{{.Slug}}
|
||||||
|
{{.Text}}
|
||||||
|
|
||||||
|
It can only be configured in the config file. By default only
|
||||||
|
"{{.Slug}}" is being used, this is the title of the ad in url format.
|
||||||
|
|
||||||
|
AD TEMPLATE
|
||||||
|
The ad listing itself can be modified as well, using the same variables
|
||||||
|
as the ad name template above.
|
||||||
|
|
||||||
|
This is the default template:
|
||||||
|
|
||||||
|
Title: {{.Title}}
|
||||||
|
Price: {{.Price}}
|
||||||
|
Id: {{.ID}}
|
||||||
|
Category: {{.Category}}
|
||||||
|
Condition: {{.Condition}}
|
||||||
|
Created: {{.Created}}
|
||||||
|
Expire: {{.Expire}}
|
||||||
|
|
||||||
|
{{.Text}}
|
||||||
|
|
||||||
|
The config parameter to modify is "template". See example.conf in the
|
||||||
|
source repository. Please take care, since this is a multiline string.
|
||||||
|
This is how it shall look if you modify it:
|
||||||
|
|
||||||
|
template="""
|
||||||
|
Title: {{.Title}}
|
||||||
|
|
||||||
|
{{.Text}}
|
||||||
|
"""
|
||||||
|
|
||||||
|
That is, the content between the two """ chars is the template.
|
||||||
|
|
||||||
SETUP
|
SETUP
|
||||||
To setup the tool, you need to lookup your userid on kleinanzeigen.de.
|
To setup the tool, you need to lookup your userid on kleinanzeigen.de.
|
||||||
Go to your ad overview page while NOT being logged in:
|
Go to your ad overview page while NOT being logged in:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ kleingebaeck - kleinanzeigen.de backup tool
|
|||||||
-l --limit <num> Limit the ads to download to <num>, default: load all.
|
-l --limit <num> Limit the ads to download to <num>, default: load all.
|
||||||
-c --config <file> Use config file <file> (default: ~/.kleingebaeck).
|
-c --config <file> Use config file <file> (default: ~/.kleingebaeck).
|
||||||
--ignoreerrors Ignore HTTP errors, may lead to incomplete ad backup.
|
--ignoreerrors Ignore HTTP errors, may lead to incomplete ad backup.
|
||||||
-f --force Download images even if they already exist.
|
-f --force Overwrite images and ads even if the already exist.
|
||||||
-m --manual Show manual.
|
-m --manual Show manual.
|
||||||
-h --help Show usage.
|
-h --help Show usage.
|
||||||
-V --version Show program version.
|
-V --version Show program version.
|
||||||
@@ -55,7 +55,7 @@ Be careful if you want to change the template. The variable is a
|
|||||||
multiline string surrounded by three double quotes. You can left out
|
multiline string surrounded by three double quotes. You can left out
|
||||||
certain fields and use any formatting you like. Refer to
|
certain fields and use any formatting you like. Refer to
|
||||||
L<https://pkg.go.dev/text/template> for details how to write a
|
L<https://pkg.go.dev/text/template> for details how to write a
|
||||||
template.
|
template. Also read the TEMPLATES section below.
|
||||||
|
|
||||||
If you're on windows and want to customize the output directory, put
|
If you're on windows and want to customize the output directory, put
|
||||||
it into single quotes to avoid the backslashes interpreted as escape
|
it into single quotes to avoid the backslashes interpreted as escape
|
||||||
@@ -63,6 +63,91 @@ chars like this:
|
|||||||
|
|
||||||
outdir = 'C:\Data\Ads'
|
outdir = 'C:\Data\Ads'
|
||||||
|
|
||||||
|
=head1 TEMPLATES
|
||||||
|
|
||||||
|
Various parts of the configuration can be modified using templates:
|
||||||
|
the output directory, the ad directory and the ad listing itself.
|
||||||
|
|
||||||
|
=head2 OUTPUT DIR TEMPLATE
|
||||||
|
|
||||||
|
The config varialbe C<outdir> or the command line parameter C<-o> take a
|
||||||
|
template which may contain:
|
||||||
|
|
||||||
|
=over
|
||||||
|
|
||||||
|
=item C<{{.Year}}>
|
||||||
|
|
||||||
|
=item C<{{.Month}}>
|
||||||
|
|
||||||
|
=item C<{{.Day}}>
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
That way you can create a new output directory for every backup
|
||||||
|
run. For example:
|
||||||
|
|
||||||
|
outdir = "/home/backups/ads-{{.Year}}-{{.Month}}-{{.Day}}"
|
||||||
|
|
||||||
|
Or using the command line flag:
|
||||||
|
|
||||||
|
-o "/home/backups/ads-{{.Year}}-{{.Month}}-{{.Day}}"
|
||||||
|
|
||||||
|
The default value is C<.> - the current directory.
|
||||||
|
|
||||||
|
=head2 AD DIRECTORY TEMPLATE
|
||||||
|
|
||||||
|
The ad directory name can be modified using the following ad values:
|
||||||
|
|
||||||
|
=over
|
||||||
|
|
||||||
|
=item {{.Price}}
|
||||||
|
|
||||||
|
=item {{.ID}}
|
||||||
|
|
||||||
|
=item {{.Category}}
|
||||||
|
|
||||||
|
=item {{.Condition}}
|
||||||
|
|
||||||
|
=item {{.Created}}
|
||||||
|
|
||||||
|
=item {{.Slug}}
|
||||||
|
|
||||||
|
=item {{.Text}}
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
It can only be configured in the config file. By default only
|
||||||
|
C<{{.Slug}}> is being used, this is the title of the ad in url format.
|
||||||
|
|
||||||
|
=head2 AD TEMPLATE
|
||||||
|
|
||||||
|
The ad listing itself can be modified as well, using the same
|
||||||
|
variables as the ad name template above.
|
||||||
|
|
||||||
|
This is the default template:
|
||||||
|
|
||||||
|
Title: {{.Title}}
|
||||||
|
Price: {{.Price}}
|
||||||
|
Id: {{.ID}}
|
||||||
|
Category: {{.Category}}
|
||||||
|
Condition: {{.Condition}}
|
||||||
|
Created: {{.Created}}
|
||||||
|
Expire: {{.Expire}}
|
||||||
|
|
||||||
|
{{.Text}}
|
||||||
|
|
||||||
|
The config parameter to modify is C<template>. See example.conf in the
|
||||||
|
source repository. Please take care, since this is a multiline
|
||||||
|
string. This is how it shall look if you modify it:
|
||||||
|
|
||||||
|
template="""
|
||||||
|
Title: {{.Title}}
|
||||||
|
|
||||||
|
{{.Text}}
|
||||||
|
"""
|
||||||
|
|
||||||
|
That is, the content between the two C<"""> chars is the template.
|
||||||
|
|
||||||
=head1 SETUP
|
=head1 SETUP
|
||||||
|
|
||||||
To setup the tool, you need to lookup your userid on
|
To setup the tool, you need to lookup your userid on
|
||||||
|
|||||||
11
main.go
11
main.go
@@ -112,17 +112,26 @@ func Main(output io.Writer) int {
|
|||||||
slog.Debug("config", "conf", conf)
|
slog.Debug("config", "conf", conf)
|
||||||
|
|
||||||
// prepare output dir
|
// prepare output dir
|
||||||
err = Mkdir(conf.Outdir)
|
outdir, err := OutDirName(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Die(err)
|
return Die(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = Mkdir(outdir)
|
||||||
|
if err != nil {
|
||||||
|
return Die(err)
|
||||||
|
}
|
||||||
|
conf.Outdir = outdir
|
||||||
|
|
||||||
// used for all HTTP requests
|
// used for all HTTP requests
|
||||||
fetch, err := NewFetcher(conf)
|
fetch, err := NewFetcher(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Die(err)
|
return Die(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup ad dir registry, needed to check for duplicates
|
||||||
|
DirsVisited = make(map[string]int)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case len(conf.Adlinks) >= 1:
|
case len(conf.Adlinks) >= 1:
|
||||||
// directly backup ad listing[s]
|
// directly backup ad listing[s]
|
||||||
|
|||||||
@@ -126,6 +126,11 @@ func ScrapeAd(fetch *Fetcher, uri string) error {
|
|||||||
|
|
||||||
advertisement.CalculateExpire()
|
advertisement.CalculateExpire()
|
||||||
|
|
||||||
|
proceed := CheckAdVisited(fetch.Config, advertisement.Slug)
|
||||||
|
if !proceed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// write listing
|
// write listing
|
||||||
addir, err := WriteAd(fetch.Config, advertisement)
|
addir, err := WriteAd(fetch.Config, advertisement)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
49
store.go
49
store.go
@@ -26,8 +26,36 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
tpl "text/template"
|
tpl "text/template"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type OutdirData struct {
|
||||||
|
Year, Day, Month string
|
||||||
|
}
|
||||||
|
|
||||||
|
func OutDirName(conf *Config) (string, error) {
|
||||||
|
tmpl, err := tpl.New("outdir").Parse(conf.Outdir)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to parse outdir template: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bytes.Buffer{}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
data := OutdirData{
|
||||||
|
Year: now.Format("2006"),
|
||||||
|
Month: now.Format("02"),
|
||||||
|
Day: now.Format("01"),
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tmpl.Execute(&buf, data)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to execute outdir template: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func AdDirName(conf *Config, advertisement *Ad) (string, error) {
|
func AdDirName(conf *Config, advertisement *Ad) (string, error) {
|
||||||
tmpl, err := tpl.New("adname").Parse(conf.Adnametemplate)
|
tmpl, err := tpl.New("adname").Parse(conf.Adnametemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -133,3 +161,24 @@ func fileExists(filename string) bool {
|
|||||||
|
|
||||||
return !info.IsDir()
|
return !info.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if an addir has already been processed by current run and
|
||||||
|
// decide what to do
|
||||||
|
func CheckAdVisited(conf *Config, adname string) bool {
|
||||||
|
if Exists(DirsVisited, adname) {
|
||||||
|
if conf.ForceDownload {
|
||||||
|
slog.Warn("an ad with the same name has already been downloaded, overwriting", "addir", adname)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't overwrite
|
||||||
|
slog.Warn("an ad with the same name has already been downloaded, skipping (use -f to overwrite)", "addir", adname)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// register
|
||||||
|
DirsVisited[adname] = 1
|
||||||
|
|
||||||
|
// overwrite
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#!/bin/sh -x
|
#!/bin/sh -x
|
||||||
base="../kleinanzeigen"
|
base="../kleinanzeigen"
|
||||||
|
|
||||||
|
rm -rf $base
|
||||||
mkdir -p $base
|
mkdir -p $base
|
||||||
|
|
||||||
echo "Generating /s-bestandsliste.html"
|
echo "Generating /s-bestandsliste.html"
|
||||||
|
|||||||
9
util.go
9
util.go
@@ -74,3 +74,12 @@ func IsNoTty() bool {
|
|||||||
func GetThrottleTime() time.Duration {
|
func GetThrottleTime() time.Duration {
|
||||||
return time.Duration(rand.Intn(MaxThrottle-MinThrottle+1)+MinThrottle) * time.Millisecond
|
return time.Duration(rand.Intn(MaxThrottle-MinThrottle+1)+MinThrottle) * time.Millisecond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// look if a key in a map exists, generic variant
|
||||||
|
func Exists[K comparable, V any](m map[K]V, v K) bool {
|
||||||
|
if _, ok := m[v]; ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user