mirror of
https://codeberg.org/scip/kleingebaeck.git
synced 2025-12-17 20:41:01 +01:00
Compare commits
9 Commits
v0.3.21
...
v0.1.0-BET
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
450d44d129 | ||
|
|
18f7e0fe49 | ||
|
|
def063afe9 | ||
| f1908f02cb | |||
| 4a528ad9d1 | |||
| 5c1161f227 | |||
| bd9d8fdb2c | |||
|
|
1ee886c504 | ||
|
|
d7b13e8a9a |
2
Makefile
2
Makefile
@@ -17,7 +17,7 @@
|
|||||||
#
|
#
|
||||||
# no need to modify anything below
|
# no need to modify anything below
|
||||||
tool = kleingebaeck
|
tool = kleingebaeck
|
||||||
VERSION = $(shell grep VERSION main.go | head -1 | cut -d '"' -f2)
|
VERSION = $(shell grep VERSION config.go | head -1 | cut -d '"' -f2)
|
||||||
archs = darwin freebsd linux windows
|
archs = darwin freebsd linux windows
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
UID = root
|
UID = root
|
||||||
|
|||||||
44
README.md
44
README.md
@@ -15,13 +15,51 @@ directory, each ad into its own subdirectory. The backup will contain
|
|||||||
a textfile `Adlisting.txt` which contains the ad contents as the
|
a textfile `Adlisting.txt` which contains the ad contents as the
|
||||||
title, body, price etc. All images will be downloaded as well.
|
title, body, price etc. All images will be downloaded as well.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
The tool doesn't need authentication and doesn't have any
|
The tool doesn't need authentication and doesn't have any
|
||||||
dependencies. Just download the binary for your platform from the
|
dependencies. Just download the binary for your platform from the
|
||||||
releases page and you're good to go.
|
releases page and you're good to go.
|
||||||
|
|
||||||
The releases also include a handy tarball which you can use to install
|
### Installation using a pre-compiled binary
|
||||||
the tool system-wide including the manual page. Just extract it and
|
|
||||||
type: `make install`.
|
Go to the [latest release
|
||||||
|
page](https://github.com/TLINDEN/kleingebaeck/releases/latest) and
|
||||||
|
look for your OS and platform. There are two options to install the binary:
|
||||||
|
|
||||||
|
1. Directly download the binary for your platoform,
|
||||||
|
e.g. `kleingebaeck-linux-amd64-0.0.5`, rename it to `kleingebaeck`
|
||||||
|
(or whatever you like more!) and put it into your bin dir
|
||||||
|
(e.g. `$HOME/bin` or as root to `/usr/local/bin`).
|
||||||
|
|
||||||
|
Be sure to verify the signature of the binary file. For this also download the matching `kleingebaeck-linux-amd64-0.0.5.sha256` file and:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cat kleingebaeck-linux-amd64-0.0.5.sha25 && sha256sum kleingebaeck-linux-amd64-0.0.5
|
||||||
|
```
|
||||||
|
You should see the same SHA256 hash.
|
||||||
|
|
||||||
|
2. You may also download a binary tarball for your platform,
|
||||||
|
e.g. `kleingebaeck-linux-amd64-0.0.5.tar.gz`, unpack and install
|
||||||
|
it. GNU Make is required for this:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
tar xvfz kleingebaeck-linux-amd64-0.0.5.tar.gz
|
||||||
|
cd kleingebaeck-linux-amd64-0.0.5
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Installation from source
|
||||||
|
|
||||||
|
You will need the Golang toolchain in order to build from source. GNU
|
||||||
|
Make will also help but is not strictly neccessary.
|
||||||
|
|
||||||
|
If you want to compile the tool yourself, use `git clone` to clone the
|
||||||
|
repository. Then execute `go mod tidy` to install all
|
||||||
|
dependencies. Then just enter `go build` or - if you have GNU Make
|
||||||
|
installed - `make`.
|
||||||
|
|
||||||
|
To install after building either copy the binary or execute `sudo make install`.
|
||||||
|
|
||||||
## Commandline options:
|
## Commandline options:
|
||||||
|
|
||||||
|
|||||||
12
config.go
12
config.go
@@ -23,21 +23,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VERSION string = "0.0.4"
|
VERSION string = "0.0.6"
|
||||||
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 = "."
|
||||||
DefaultTemplate string = "Title: {{.Title}}\nPrice: {{.Price}}\nId: {{.Id}}\n" +
|
DefaultTemplate string = "Title: {{.Title}}\nPrice: {{.Price}}\nId: {{.Id}}\n" +
|
||||||
"Category: {{.Category}}\nCondition: {{.Condition}}\nCreated: {{.Created}}\n\n{{.Text}}\n"
|
"Category: {{.Category}}\nCondition: {{.Condition}}\nCreated: {{.Created}}\n\n{{.Text}}\n"
|
||||||
|
DefaultTemplateWin string = "Title: {{.Title}}\r\nPrice: {{.Price}}\r\nId: {{.Id}}\r\n" +
|
||||||
|
"Category: {{.Category}}\r\nCondition: {{.Condition}}\r\nCreated: {{.Created}}\r\n\r\n{{.Text}}\r\n"
|
||||||
Useragent string = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
|
Useragent string = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
|
||||||
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Verbose bool `hcl:"verbose"`
|
Verbose *bool `hcl:"verbose"`
|
||||||
User int `hcl:"user"`
|
User *int `hcl:"user"`
|
||||||
Outdir string `hcl:"outdir"`
|
Outdir *string `hcl:"outdir"`
|
||||||
Template string `hcl:"template"`
|
Template *string `hcl:"template"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseConfigfile(file string) (*Config, error) {
|
func ParseConfigfile(file string) (*Config, error) {
|
||||||
|
|||||||
18
main.go
18
main.go
@@ -22,6 +22,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
|
||||||
"github.com/lmittmann/tint"
|
"github.com/lmittmann/tint"
|
||||||
@@ -109,7 +110,7 @@ func Main() int {
|
|||||||
return Die(err)
|
return Die(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if enableverbose || conf.Verbose {
|
if enableverbose || *conf.Verbose {
|
||||||
logLevel.Set(slog.LevelInfo)
|
logLevel.Set(slog.LevelInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,8 +136,8 @@ func Main() int {
|
|||||||
slog.Debug("config", "conf", conf)
|
slog.Debug("config", "conf", conf)
|
||||||
|
|
||||||
if len(dir) == 0 {
|
if len(dir) == 0 {
|
||||||
if len(conf.Outdir) > 0 {
|
if len(*conf.Outdir) > 0 {
|
||||||
dir = conf.Outdir
|
dir = *conf.Outdir
|
||||||
} else {
|
} else {
|
||||||
dir = Defaultdir
|
dir = Defaultdir
|
||||||
}
|
}
|
||||||
@@ -150,8 +151,11 @@ func Main() int {
|
|||||||
|
|
||||||
// which template to use
|
// which template to use
|
||||||
template := DefaultTemplate
|
template := DefaultTemplate
|
||||||
if len(conf.Template) > 0 {
|
if runtime.GOOS == "windows" {
|
||||||
template = conf.Template
|
template = DefaultTemplateWin
|
||||||
|
}
|
||||||
|
if len(*conf.Template) > 0 {
|
||||||
|
template = *conf.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
// directly backup ad listing[s]
|
// directly backup ad listing[s]
|
||||||
@@ -167,8 +171,8 @@ func Main() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// backup all ads of the given user (via config or cmdline)
|
// backup all ads of the given user (via config or cmdline)
|
||||||
if uid == 0 && conf.User > 0 {
|
if uid == 0 && *conf.User > 0 {
|
||||||
uid = conf.User
|
uid = *conf.User
|
||||||
}
|
}
|
||||||
|
|
||||||
if uid > 0 {
|
if uid > 0 {
|
||||||
|
|||||||
5
mkrel.sh
5
mkrel.sh
@@ -40,6 +40,11 @@ for D in $DIST; do
|
|||||||
os=${D/\/*/}
|
os=${D/\/*/}
|
||||||
arch=${D/*\//}
|
arch=${D/*\//}
|
||||||
binfile="releases/${tool}-${os}-${arch}-${version}"
|
binfile="releases/${tool}-${os}-${arch}-${version}"
|
||||||
|
|
||||||
|
if test "$os" = "windows"; then
|
||||||
|
binfile="${binfile}.exe"
|
||||||
|
fi
|
||||||
|
|
||||||
tardir="${tool}-${os}-${arch}-${version}"
|
tardir="${tool}-${os}-${arch}-${version}"
|
||||||
tarfile="releases/${tool}-${os}-${arch}-${version}.tar.gz"
|
tarfile="releases/${tool}-${os}-${arch}-${version}.tar.gz"
|
||||||
set -x
|
set -x
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -176,7 +177,7 @@ func ScrapeImages(dir string, ad *Ad) error {
|
|||||||
failure := make(chan string)
|
failure := make(chan string)
|
||||||
|
|
||||||
for _, imguri := range ad.Images {
|
for _, imguri := range ad.Images {
|
||||||
file := fmt.Sprintf("%s/%d.jpg", dir, img)
|
file := filepath.Join(dir, ad.Slug, fmt.Sprintf("%d.jpg", img))
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
err := Getimage(imguri, file)
|
err := Getimage(imguri, file)
|
||||||
|
|||||||
10
store.go
10
store.go
@@ -21,26 +21,32 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
tpl "text/template"
|
tpl "text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
func WriteAd(dir string, ad *Ad, template string) error {
|
func WriteAd(dir string, ad *Ad, template string) error {
|
||||||
// prepare output dir
|
// prepare output dir
|
||||||
dir = dir + "/" + ad.Slug
|
dir = filepath.Join(dir, ad.Slug)
|
||||||
err := Mkdir(dir)
|
err := Mkdir(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// write ad file
|
// write ad file
|
||||||
listingfile := strings.Join([]string{dir, "Adlisting.txt"}, "/")
|
listingfile := filepath.Join(dir, "Adlisting.txt")
|
||||||
f, err := os.Create(listingfile)
|
f, err := os.Create(listingfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
ad.Text = strings.ReplaceAll(ad.Text, "<br/>", "\r\n")
|
||||||
|
} else {
|
||||||
ad.Text = strings.ReplaceAll(ad.Text, "<br/>", "\n")
|
ad.Text = strings.ReplaceAll(ad.Text, "<br/>", "\n")
|
||||||
|
}
|
||||||
|
|
||||||
tmpl, err := tpl.New("adlisting").Parse(template)
|
tmpl, err := tpl.New("adlisting").Parse(template)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user