feat: Updated to use new login/auth procedure on ZiniGo side - uses cookies for the token.

Also added a -playwright=true option for people who dont want to use a pre-installed chrome. Added macos build scripts (and executable)
This commit is contained in:
TheAxeDude 2021-07-03 20:06:14 +02:00
parent cf16f9956a
commit d79c20d8ac
6 changed files with 72 additions and 19 deletions

View File

@ -7,6 +7,7 @@ import (
"fmt" "fmt"
wkhtml "github.com/SebastiaanKlippert/go-wkhtmltopdf" wkhtml "github.com/SebastiaanKlippert/go-wkhtmltopdf"
"github.com/icza/gox/stringsx" "github.com/icza/gox/stringsx"
"github.com/mxschmitt/playwright-go"
"github.com/pdfcpu/pdfcpu/pkg/api" "github.com/pdfcpu/pdfcpu/pkg/api"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"io/ioutil" "io/ioutil"
@ -37,6 +38,7 @@ func main() {
chromePtr := flag.String("c", "google-chrome", "Chrome executable") chromePtr := flag.String("c", "google-chrome", "Chrome executable")
zinioHostPtr := flag.String("e", "api-sec.ziniopro.com", "Zinio Host (Excluding port and URI Scheme). Known: `api-sec`, `api-sec-2`") zinioHostPtr := flag.String("e", "api-sec.ziniopro.com", "Zinio Host (Excluding port and URI Scheme). Known: `api-sec`, `api-sec-2`")
exportUsingWKHTML := flag.String("wkhtml", "false", "Use WKHTML instead of Chrome to generate PDF (false by default)") exportUsingWKHTML := flag.String("wkhtml", "false", "Use WKHTML instead of Chrome to generate PDF (false by default)")
exportUsingPlaywright := flag.String("playwright", "false", "Use Playwright Chromium instead of local Chrome to generate PDF (false by default)")
flag.Parse() flag.Parse()
@ -68,13 +70,13 @@ func main() {
} }
fmt.Println("Starting the application...") //fmt.Println("Starting the application...")
initialToken, err := GetInitialToken() //initialToken, err := GetInitialToken()
if err != nil { //if err != nil {
os.Exit(1) // os.Exit(1)
} //}
loginToken := GetLoginToken(initialToken, *usernamePtr, *passwordPtr) loginToken := GetLoginToken(*usernamePtr, *passwordPtr)
issues := GetLibrary(loginToken, initialToken, *zinioHostPtr) issues := GetLibrary(loginToken, *zinioHostPtr)
for i := range issues { for i := range issues {
issueList := issues[i] issueList := issues[i]
//fmt.Println("Found " + strconv.Itoa(len(issues.Data)) + " issues in library.") //fmt.Println("Found " + strconv.Itoa(len(issues.Data)) + " issues in library.")
@ -84,7 +86,7 @@ func main() {
template, _ := ioutil.ReadFile("template.html") template, _ := ioutil.ReadFile("template.html")
if template == nil || len(template) == 0 { if template == nil || len(template) == 0 {
fmt.Println("template.html not found, or empty. using built in template. Consider changing this if your files are cropped.") fmt.Println("template.html not found, or empty. using issue in template. Consider changing this if your files are cropped.")
template = []byte(defaultTemplate) template = []byte(defaultTemplate)
} }
@ -108,7 +110,7 @@ func main() {
} }
fmt.Println("Downloading issue: " + publicationName + " - " + issueName) fmt.Println("Downloading issue: " + publicationName + " - " + issueName)
pages := GetPages(loginToken, issue, initialToken, *zinioHostPtr) pages := GetPages(loginToken, issue, *zinioHostPtr)
var filenames []string var filenames []string
@ -141,7 +143,24 @@ func main() {
//convert to pdf //convert to pdf
if strings.ToLower(*exportUsingWKHTML) == "true" { if strings.ToLower(*exportUsingPlaywright) == "true" {
pw, err := playwright.Run()
if err != nil {
log.Fatalf("could not start playwright: %v", err)
}
browser, err := pw.Chromium.Launch()
if err != nil {
log.Fatalf("could not launch browser: %v", err)
}
context, err := browser.NewContext()
page, err := context.NewPage()
_ = page.SetContent(htmldata, playwright.PageSetContentOptions{WaitUntil: playwright.WaitUntilStateNetworkidle})
_, err = page.PDF(playwright.PagePdfOptions{
Path: playwright.String(pathString + ".pdf"),
})
} else if strings.ToLower(*exportUsingWKHTML) == "true" {
pdfg, err := wkhtml.NewPDFGenerator() pdfg, err := wkhtml.NewPDFGenerator()
if err != nil { if err != nil {
@ -210,7 +229,7 @@ func main() {
} }
func GetPages(userToken LoginResponse, issue LibraryData, token string, endpoint string) Response { func GetPages(userToken LoginResponse, issue LibraryData, endpoint string) Response {
client := &http.Client{} client := &http.Client{}
@ -218,8 +237,10 @@ func GetPages(userToken LoginResponse, issue LibraryData, token string, endpoint
req, _ := http.NewRequest("GET", "https://zinio.com/api/newsstand/newsstands/101/issues/"+strconv.Itoa(issue.Id)+"/content/pages?format=svg&application_id=9901&css_content=true&user_id="+userToken.Data.User.UserIDString, nil) req, _ := http.NewRequest("GET", "https://zinio.com/api/newsstand/newsstands/101/issues/"+strconv.Itoa(issue.Id)+"/content/pages?format=svg&application_id=9901&css_content=true&user_id="+userToken.Data.User.UserIDString, nil)
req.Header.Add("Content-Type", "application/json") req.Header.Add("Content-Type", "application/json")
req.AddCookie(&http.Cookie{Name: "zwrt", Value: userToken.Data.AccessToken})
//req.Header.Add("Authorization", "bearer "+token) //req.Header.Add("Authorization", "bearer "+token)
req.Header.Add("Authorization", token) //req.Header.Add("Authorization", token)
resp, _ := client.Do(req) resp, _ := client.Do(req)
data, _ := ioutil.ReadAll(resp.Body) data, _ := ioutil.ReadAll(resp.Body)
@ -247,14 +268,14 @@ func GetInitialToken() (token string, err error) {
return string(found[2]), nil return string(found[2]), nil
} }
func GetLoginToken(initialToken string, username string, password string) LoginResponse { func GetLoginToken(username string, password string) LoginResponse {
client := &http.Client{} client := &http.Client{}
var jsonStr = []byte(`{"username":"` + username + `","password":"` + password + `"}`) var jsonStr = []byte(`{"username":"` + username + `","password":"` + password + `"}`)
req, _ := http.NewRequest("POST", "https://www.zinio.com/api/login?project=99&logger=null", bytes.NewBuffer(jsonStr)) req, _ := http.NewRequest("POST", "https://www.zinio.com/api/login?project=99&logger=null", bytes.NewBuffer(jsonStr))
req.Header.Add("Content-Type", "application/json") req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", initialToken) //req.Header.Add("Authorization", initialToken)
resp, _ := client.Do(req) resp, _ := client.Do(req)
data, _ := ioutil.ReadAll(resp.Body) data, _ := ioutil.ReadAll(resp.Body)
@ -263,11 +284,20 @@ func GetLoginToken(initialToken string, username string, password string) LoginR
_ = json.Unmarshal([]byte(data), &responseType) _ = json.Unmarshal([]byte(data), &responseType)
for _, cookie := range resp.Cookies() {
if cookie.Name == "zwrt" {
responseType.Data.AccessToken = cookie.Value
}
if cookie.Name == "zwrrt" {
responseType.Data.RefreshToken = cookie.Value
}
}
return responseType return responseType
} }
func GetLibrary(userToken LoginResponse, initialToken string, endpoint string) []LibraryResponse { func GetLibrary(userToken LoginResponse, endpoint string) []LibraryResponse {
client := &http.Client{} client := &http.Client{}
var itemsToReturn []LibraryResponse var itemsToReturn []LibraryResponse
@ -278,8 +308,9 @@ func GetLibrary(userToken LoginResponse, initialToken string, endpoint string) [
req, _ := http.NewRequest("GET", "https://zinio.com/api/newsstand/newsstands/101/users/"+userToken.Data.User.UserIDString+"/library_issues?limit="+strconv.Itoa(issuesToFetch)+"&page="+strconv.Itoa(pageToFetch), nil) req, _ := http.NewRequest("GET", "https://zinio.com/api/newsstand/newsstands/101/users/"+userToken.Data.User.UserIDString+"/library_issues?limit="+strconv.Itoa(issuesToFetch)+"&page="+strconv.Itoa(pageToFetch), nil)
req.Header.Add("Content-Type", "application/json") req.Header.Add("Content-Type", "application/json")
req.AddCookie(&http.Cookie{Name: "zwrt", Value: userToken.Data.AccessToken})
//req.Header.Add("Authorization", "bearer "+userToken.Data.Token.AccessToken) //req.Header.Add("Authorization", "bearer "+userToken.Data.Token.AccessToken)
req.Header.Add("Authorization", initialToken) //req.Header.Add("Authorization", initialToken)
resp, err := client.Do(req) resp, err := client.Do(req)
@ -321,6 +352,7 @@ type LoginData struct {
User User `json:"user"` User User `json:"user"`
Token Token `json:"token"` Token Token `json:"token"`
RefreshToken string `json:"refreshToken"` RefreshToken string `json:"refreshToken"`
AccessToken string
} }
type User struct { type User struct {

View File

@ -12,16 +12,22 @@ ZiniGo can be downloaded for Windows and Linux at https://github.com/TheAxeDude/
You can also add these properties to a config file in the working directory, instead of passing them in manually. See the sample at https://github.com/TheAxeDude/ZiniGo/blob/master/config.json You can also add these properties to a config file in the working directory, instead of passing them in manually. See the sample at https://github.com/TheAxeDude/ZiniGo/blob/master/config.json
You can use `-playwright=true` to use Playwright to run the tests. It'll download a browser in the background.
## Requirements ## Requirements
Google chrome installed, and accessible via the command `google-chrome`, or at a location passed in via the -c parameter.
No specific dependencies need to be installed, however you can specify the location of the chrome executable to be used rendering the PDF.
If using a pre-installed chrome, the command `google-chrome` should work, or a location of the Chrome executable should be passed in via the `-c` parameter.
## How it works ## How it works
ZiniGo logs into Zinio, and pulls a list of all issues purchased. ZiniGo logs into Zinio, and pulls a list of all issues purchased.
Each page is available as an SVG, which is then injected into an HTML page (based on template.html). Each page is available as an SVG, which is then injected into an HTML page (based on template.html).
google-chrome is then used to print the page to PDF, and all pages are combined into a single PDF. PlayWright (or google-chrome) is then used to print the page to PDF, and all pages are combined into a single PDF.
## Building ## Building
Build for linux & windows on windows using the pwershell script in buildscripts Build for linux & windows on windows using the powershell script in buildscripts
Build for linux & windows on macos using the darwin.sh script in buildscripts

15
buildscripts/darwin.sh Normal file
View File

@ -0,0 +1,15 @@
set GOOS = 'windows'
set GOARCH = 'amd64'
cd ..
go build -o built/Zinigo_Windows_x64.exe Grabazine.go
cd buildscripts
set GOOS = 'linux'
set GOARCH = 'amd64'
cd ..
go build -o built/Zinigo_Linux_AMD64 Grabazine.go
cd buildscripts
set GOOS=darwin
set GOARCH=amd64
cd ..
go build -o built/Zinigo_Macos_AMD64 Grabazine.go
cd buildscripts

BIN
built/Zinigo_Linux_AMD64 Normal file → Executable file

Binary file not shown.

BIN
built/Zinigo_Macos_AMD64 Executable file

Binary file not shown.

BIN
built/Zinigo_Windows_x64.exe Normal file → Executable file

Binary file not shown.