Push old code
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
pixiv-scrapper
 | 
			
		||||
.directory
 | 
			
		||||
							
								
								
									
										159
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	"./pixiv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type cmdlineT struct {
 | 
			
		||||
	followings    bool
 | 
			
		||||
	favs          bool
 | 
			
		||||
	illusts       bool
 | 
			
		||||
	userID        string
 | 
			
		||||
	setCookies    string
 | 
			
		||||
	setProxy      string
 | 
			
		||||
	workDirectory string
 | 
			
		||||
	userAgent     string
 | 
			
		||||
	printID       bool
 | 
			
		||||
	printURL      bool
 | 
			
		||||
	test          bool
 | 
			
		||||
	logErrorsFile string
 | 
			
		||||
	threads       int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	cmdline cmdlineT
 | 
			
		||||
	cookies string
 | 
			
		||||
	pix     pixiv.Pixiv
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	flags()
 | 
			
		||||
	pix = pixiv.New(cmdline.setCookies, cmdline.logErrorsFile, cmdline.threads)
 | 
			
		||||
	defer pix.Close()
 | 
			
		||||
	if len(cmdline.setProxy) > 0 {
 | 
			
		||||
		pix.SetProxy(cmdline.setProxy)
 | 
			
		||||
	}
 | 
			
		||||
	if len(cmdline.workDirectory) > 0 {
 | 
			
		||||
		pix.WorkDirectory = cmdline.workDirectory
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if cmdline.illusts {
 | 
			
		||||
		err := fetchIllusts(cmdline.userID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if cmdline.favs {
 | 
			
		||||
		err := fetchBookmarks(cmdline.userID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if cmdline.followings {
 | 
			
		||||
		err := fetchFollows(cmdline.userID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err.Error())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fetchFollows(userID string) (err error) {
 | 
			
		||||
	users, err := pix.GetFollows(userID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	for _, user := range users {
 | 
			
		||||
		fmt.Printf("%s %s %s %s\n", user.UserID, "followed_user", "defered", user.UserName)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fetchBookmarks(userID string) (err error) {
 | 
			
		||||
	illusts, err := pix.GetBookmarks(userID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	for _, illust := range illusts {
 | 
			
		||||
		if cmdline.printID {
 | 
			
		||||
			fmt.Printf("%s %s %s %s %s\n", illust.ID, "illust", "defered", illust.Title, illust.Alt)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if !illust.Complited() {
 | 
			
		||||
			err := pix.ComplateIllust(&illust)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if cmdline.printURL {
 | 
			
		||||
			for _, page := range illust.Pages {
 | 
			
		||||
				fmt.Println(page.URLs.Original)
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if !(cmdline.printURL && cmdline.printID) {
 | 
			
		||||
			if !(cmdline.printURL && cmdline.printID) {
 | 
			
		||||
				for _, illust := range illusts {
 | 
			
		||||
					pix.DownloadChannel <- illust
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fetchIllusts(userID string) (err error) {
 | 
			
		||||
	illusts, err := pix.GetUserIllustsID(userID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if cmdline.printID {
 | 
			
		||||
		for _, illust := range illusts {
 | 
			
		||||
			fmt.Println(illust.ID)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if cmdline.printURL {
 | 
			
		||||
		for _, illust := range illusts {
 | 
			
		||||
			id := illust.ID
 | 
			
		||||
			illust, err := pix.GetIllust(id)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			for _, page := range illust.Pages {
 | 
			
		||||
				fmt.Println(page.URLs.Original)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if !(cmdline.printURL && cmdline.printID) {
 | 
			
		||||
		for _, illust := range illusts {
 | 
			
		||||
			pix.DownloadChannel <- illust
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func flags() {
 | 
			
		||||
	flag.BoolVar(&cmdline.illusts, "illusts", false, "download illusts")
 | 
			
		||||
	flag.BoolVar(&cmdline.followings, "followings", false, "fetch user followings")
 | 
			
		||||
	flag.BoolVar(&cmdline.favs, "favs", false, "fetch user favorites")
 | 
			
		||||
	flag.StringVar(&cmdline.userID, "user-id", "", "set userID to extract followings, favs or illustrations from")
 | 
			
		||||
	flag.StringVar(&cmdline.setCookies, "set-cookies", "", "set cookies for request. PHPSESSID is REQUIRED if you want to see R-18 works. SHOULD be something like PHPSESSID=12345678_MEPujYEEwOfXKYdB9TXeMIxaq7pQPYXA")
 | 
			
		||||
	flag.StringVar(&cmdline.setProxy, "set-proxy", "", "set proxy for request")
 | 
			
		||||
	flag.StringVar(&cmdline.workDirectory, "workdir", "", "set directory to save images in")
 | 
			
		||||
	flag.StringVar(&cmdline.userAgent, "user-agent", "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0", "set user agent")
 | 
			
		||||
	flag.BoolVar(&cmdline.printID, "print-id", false, "only print IDs, not download")
 | 
			
		||||
	flag.BoolVar(&cmdline.printURL, "print-url", false, "only print URLs, not download")
 | 
			
		||||
	flag.BoolVar(&cmdline.test, "test", false, "test")
 | 
			
		||||
	flag.StringVar(&cmdline.logErrorsFile, "log-errors", "", "file to strore failed items")
 | 
			
		||||
	flag.IntVar(&cmdline.threads, "threads", 1, "threads number")
 | 
			
		||||
	flag.Parse()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										70
									
								
								pixiv/ajax.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								pixiv/ajax.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
package pixiv
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ajaxResp struct {
 | 
			
		||||
	Error   bool            `json:"error"`
 | 
			
		||||
	Message string          `json:"message"`
 | 
			
		||||
	Body    json.RawMessage `json:"body"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Pixiv) ajaxRequest(addr string) (r json.RawMessage, err error) {
 | 
			
		||||
	req, err := http.NewRequest("GET", addr, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		err = fmt.Errorf("NewRequest failed (%s)", addr)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	req.AddCookie(&p.phpsessid)
 | 
			
		||||
	req.Header.Set("User-Agent", p.Ua)
 | 
			
		||||
	req.Header.Set("Referer", "https://www.pixiv.net")
 | 
			
		||||
	var resp *http.Response
 | 
			
		||||
	for i := 0; i < p.RetryCount; i++ {
 | 
			
		||||
		resp, err = p.client.Do(req)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Printf("%s", err.Error())
 | 
			
		||||
			log.Printf("Retry %d of %d...", i, p.RetryCount)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		defer resp.Body.Close()
 | 
			
		||||
		if resp.StatusCode != http.StatusOK {
 | 
			
		||||
			log.Printf("GET %s failed: bad status code: %d", addr, resp.StatusCode)
 | 
			
		||||
			log.Printf("Retry %d of %d...", i, p.RetryCount)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		break
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("%s", err.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if resp.StatusCode != http.StatusOK {
 | 
			
		||||
		log.Printf("GET %s failed: bad status code: %d", addr, resp.StatusCode)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	respData, err := ioutil.ReadAll(resp.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println("ioutil.ReadAll(resp.Body) failed")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var ajax ajaxResp
 | 
			
		||||
	err = json.Unmarshal(respData, &ajax)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println("json.Unmarshal(respData, &ajax) failed")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if ajax.Error {
 | 
			
		||||
		err = errors.New(ajax.Message)
 | 
			
		||||
		log.Println("ajax error")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	r = ajax.Body
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										122
									
								
								pixiv/downloader.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								pixiv/downloader.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
package pixiv
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//DownloadIllust .
 | 
			
		||||
func (p *Pixiv) downloadIllust(i Illust) (err error) {
 | 
			
		||||
	if !i.Complited() {
 | 
			
		||||
		err = p.ComplateIllust(&i)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	getExtension := func(fullpath string) (ext string) {
 | 
			
		||||
		parts := strings.Split(fullpath, ".")
 | 
			
		||||
		ext = parts[len(parts)-1]
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	type artworkFile struct {
 | 
			
		||||
		directory string
 | 
			
		||||
		filename  string
 | 
			
		||||
		url       string
 | 
			
		||||
	}
 | 
			
		||||
	type artwork struct {
 | 
			
		||||
		tags  []string
 | 
			
		||||
		files []artworkFile
 | 
			
		||||
	}
 | 
			
		||||
	var art artwork
 | 
			
		||||
	for _, tag := range i.Tags.Tags {
 | 
			
		||||
		if len(tag.Translation.En) > 0 {
 | 
			
		||||
			art.tags = append(art.tags, tag.Translation.En)
 | 
			
		||||
		} else if len(tag.Romaji) > 0 {
 | 
			
		||||
			art.tags = append(art.tags, tag.Romaji)
 | 
			
		||||
		} else {
 | 
			
		||||
			art.tags = append(art.tags, tag.Tag)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for pageNumber, page := range i.Pages {
 | 
			
		||||
		directory := fmt.Sprintf("%s/%s_%s/", p.WorkDirectory, i.UserID, i.UserAccount)
 | 
			
		||||
		filename := fmt.Sprintf("%s_p%d.%s", i.ID, pageNumber, getExtension(page.URLs.Original))
 | 
			
		||||
		art.files = append(art.files,
 | 
			
		||||
			artworkFile{directory: directory,
 | 
			
		||||
				filename: filename,
 | 
			
		||||
				url:      page.URLs.Original})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, file := range art.files {
 | 
			
		||||
		err := os.MkdirAll(file.directory, 0755)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		outfile, err := os.Create(file.directory + file.filename)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		defer outfile.Close()
 | 
			
		||||
		//log.Printf("Downloading %s to %s", file.url, outfile.Name())
 | 
			
		||||
		err = p.downloadTo(file.url, outfile)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Pixiv) downloadTo(addr string, file *os.File) (err error) {
 | 
			
		||||
	req, err := http.NewRequest("GET", addr, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		err = fmt.Errorf("NewRequest failed (%s)", addr)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	req.AddCookie(&p.phpsessid)
 | 
			
		||||
	req.Header.Set("User-Agent", p.Ua)
 | 
			
		||||
	req.Header.Set("Referer", "https://www.pixiv.net")
 | 
			
		||||
	var resp *http.Response
 | 
			
		||||
	for i := 0; i < p.RetryCount; i++ {
 | 
			
		||||
		resp, err = p.client.Do(req)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Printf("%s", err.Error())
 | 
			
		||||
			log.Printf("Retry %d of %d...", i, p.RetryCount)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		defer resp.Body.Close()
 | 
			
		||||
		if resp.StatusCode != http.StatusOK {
 | 
			
		||||
			log.Printf("GET %s failed: bad status code: %d", addr, resp.StatusCode)
 | 
			
		||||
			log.Printf("Retry %d of %d...", i, p.RetryCount)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		err = file.Truncate(0)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		_, err = io.Copy(file, resp.Body)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Printf("%s", err.Error())
 | 
			
		||||
			log.Printf("Retry %d of %d...", i, p.RetryCount)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		break
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Pixiv) downloadWorker() {
 | 
			
		||||
	for illust := range p.DownloadChannel {
 | 
			
		||||
		err := p.downloadIllust(illust)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			p.logChannel <- fmt.Sprintf("%s %s %s\n", illust.ID, "illust", "failed")
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		p.logChannel <- fmt.Sprintf("%s %s %s\n", illust.ID, "illust", "downloaded")
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								pixiv/new.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								pixiv/new.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
package pixiv
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"h12.io/socks"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//Pixiv is API
 | 
			
		||||
type Pixiv struct {
 | 
			
		||||
	phpsessid       http.Cookie
 | 
			
		||||
	Ua              string
 | 
			
		||||
	client          *http.Client
 | 
			
		||||
	RetryCount      int
 | 
			
		||||
	ItemsPerRequest int
 | 
			
		||||
	WorkDirectory   string
 | 
			
		||||
	logChannel      chan string
 | 
			
		||||
	DownloadChannel chan Illust
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//New returns object with methods to access API functions
 | 
			
		||||
func New(cookies string, logFilePath string, threads int) (p Pixiv) {
 | 
			
		||||
	p.phpsessid = http.Cookie{Name: "PHPSESSID", Value: cookies}
 | 
			
		||||
	p.Ua = "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0"
 | 
			
		||||
	p.client = &http.Client{}
 | 
			
		||||
	p.RetryCount = 5
 | 
			
		||||
	p.ItemsPerRequest = 100
 | 
			
		||||
	p.WorkDirectory = fmt.Sprintf("%s/Pictures/pixiv", os.Getenv("HOME"))
 | 
			
		||||
	if len(logFilePath) > 0 {
 | 
			
		||||
		logfile, err := os.OpenFile(logFilePath, os.O_APPEND, 664)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Fatal(err.Error())
 | 
			
		||||
		}
 | 
			
		||||
		p.logChannel = make(chan string)
 | 
			
		||||
		go p.logger(logfile)
 | 
			
		||||
	} else {
 | 
			
		||||
		p.logChannel = make(chan string)
 | 
			
		||||
		go p.logger(os.Stdout)
 | 
			
		||||
	}
 | 
			
		||||
	p.DownloadChannel = make(chan Illust)
 | 
			
		||||
	for i := 0; i < threads; i++ {
 | 
			
		||||
		go p.downloadWorker()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Close .
 | 
			
		||||
func (p *Pixiv) Close() {
 | 
			
		||||
	close(p.logChannel)
 | 
			
		||||
	close(p.DownloadChannel)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *Pixiv) logger(logfile *os.File) {
 | 
			
		||||
	for entry := range p.logChannel {
 | 
			
		||||
		logfile.WriteString(entry)
 | 
			
		||||
	}
 | 
			
		||||
	log.Println("Closing log file")
 | 
			
		||||
	logfile.Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//SetProxy sets SOCKS proxy for all requests
 | 
			
		||||
func (p *Pixiv) SetProxy(proxy string) (err error) {
 | 
			
		||||
	dialSocksProxy := socks.Dial(proxy)
 | 
			
		||||
	tr := &http.Transport{Dial: dialSocksProxy}
 | 
			
		||||
	p.client.Transport = tr
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										155
									
								
								pixiv/pixiv.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								pixiv/pixiv.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,155 @@
 | 
			
		||||
package pixiv
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//GetBookmarks .
 | 
			
		||||
func (p *Pixiv) GetBookmarks(userID string) (illusts []Illust, err error) {
 | 
			
		||||
	type ajaxBody struct {
 | 
			
		||||
		Works []struct {
 | 
			
		||||
			ID string `json:"id"`
 | 
			
		||||
		} `json:"works"`
 | 
			
		||||
		Total int `json:"total"`
 | 
			
		||||
	}
 | 
			
		||||
	offset := 0
 | 
			
		||||
	for {
 | 
			
		||||
		req := fmt.Sprintf("https://www.pixiv.net/ajax/user/%s/illusts/bookmarks?tag=&offset=%d&limit=%d&rest=show&lang=en", userID, offset, p.ItemsPerRequest)
 | 
			
		||||
		rawAjaxBody, err := p.ajaxRequest(req)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		var body ajaxBody
 | 
			
		||||
		err = json.Unmarshal(rawAjaxBody, &body)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		for _, illust := range body.Works {
 | 
			
		||||
			illusts = append(illusts, Illust{ID: illust.ID, complited: false})
 | 
			
		||||
		}
 | 
			
		||||
		if len(illusts) < body.Total {
 | 
			
		||||
			offset = len(illusts)
 | 
			
		||||
			log.Printf("Fetched %d/%d bookmarks", offset, body.Total)
 | 
			
		||||
			continue
 | 
			
		||||
		} else {
 | 
			
		||||
			log.Printf("Fetched all %d bookmarks of user %s", offset, userID)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//GetFollows .
 | 
			
		||||
func (p *Pixiv) GetFollows(userID string) (users []User, err error) {
 | 
			
		||||
	type ajaxBody struct {
 | 
			
		||||
		Users []User `json:"users"`
 | 
			
		||||
		Total int    `json:"total"`
 | 
			
		||||
	}
 | 
			
		||||
	offset := 0
 | 
			
		||||
	for {
 | 
			
		||||
		req := fmt.Sprintf("https://www.pixiv.net/ajax/user/%s/following?offset=%d&limit=%d&rest=show&tag=&lang=en", userID, offset, p.ItemsPerRequest)
 | 
			
		||||
		rawAjaxBody, err := p.ajaxRequest(req)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		var body ajaxBody
 | 
			
		||||
		err = json.Unmarshal(rawAjaxBody, &body)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		users = append(users, body.Users[:]...)
 | 
			
		||||
		if len(users) < body.Total {
 | 
			
		||||
			offset = len(users)
 | 
			
		||||
			log.Printf("Fetched %d/%d follows", offset, body.Total)
 | 
			
		||||
			continue
 | 
			
		||||
		} else {
 | 
			
		||||
			log.Printf("Fetched all %d follows of user %s", offset, userID)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//GetIllust .
 | 
			
		||||
func (p *Pixiv) GetIllust(illustID string) (r Illust, err error) {
 | 
			
		||||
	req := fmt.Sprintf("https://www.pixiv.net/ajax/illust/%s?lang=en", illustID)
 | 
			
		||||
	apiResp, err := p.ajaxRequest(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	err = json.Unmarshal(apiResp, &r)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Unmarshaling of api response returned an error: %s", err.Error())
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if r.PageCount > 1 {
 | 
			
		||||
		req := fmt.Sprintf("https://www.pixiv.net/ajax/illust/%s/pages?lang=en", illustID)
 | 
			
		||||
		apiResp, err := p.ajaxRequest(req)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return Illust{}, err
 | 
			
		||||
		}
 | 
			
		||||
		err = json.Unmarshal(apiResp, &r.Pages)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Printf("Unmarshaling of api response returned an error: %s", err.Error())
 | 
			
		||||
			return Illust{}, err
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		var page IllustPage
 | 
			
		||||
		page.URLs = r.URLs
 | 
			
		||||
		page.Width = r.Width
 | 
			
		||||
		page.Height = r.Height
 | 
			
		||||
		r.Pages = append(r.Pages, page)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//GetUserIllustsID .
 | 
			
		||||
func (p *Pixiv) GetUserIllustsID(userID string) (illusts []Illust, err error) {
 | 
			
		||||
	type ajaxBody struct {
 | 
			
		||||
		Illusts map[string]interface{} `json:"illusts"`
 | 
			
		||||
	}
 | 
			
		||||
	var body ajaxBody
 | 
			
		||||
	req := fmt.Sprintf("https://www.pixiv.net/ajax/user/%s/profile/all?lang=en", userID)
 | 
			
		||||
	rawAjaxBody, err := p.ajaxRequest(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	err = json.Unmarshal(rawAjaxBody, &body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for ID := range body.Illusts {
 | 
			
		||||
		illusts = append(illusts, Illust{ID: ID, complited: false})
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//ComplateIllust .
 | 
			
		||||
func (p *Pixiv) ComplateIllust(illust *Illust) (err error) {
 | 
			
		||||
	*illust, err = p.GetIllust(illust.ID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	illust.complited = true
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//ComplateIllustMultiple .
 | 
			
		||||
func (p *Pixiv) ComplateIllustMultiple(illusts *[]Illust) (err error) {
 | 
			
		||||
	for i, illust := range *illusts {
 | 
			
		||||
		(*illusts)[i], err = p.GetIllust(illust.ID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		(*illusts)[i].complited = true
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Complited .
 | 
			
		||||
func (i *Illust) Complited() bool {
 | 
			
		||||
	return i.complited
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										83
									
								
								pixiv/types.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								pixiv/types.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
package pixiv
 | 
			
		||||
 | 
			
		||||
//Illust .
 | 
			
		||||
type Illust struct {
 | 
			
		||||
	complited     bool
 | 
			
		||||
	ID            string `json:"id"`
 | 
			
		||||
	IlustID       string `json:"illustId"`
 | 
			
		||||
	Title         string `json:"title"`
 | 
			
		||||
	IllustTitle   string `json:"illustTitle"`
 | 
			
		||||
	IllustComment string `json:"illustComment"`
 | 
			
		||||
	IllustType    int    `json:"illustType"`
 | 
			
		||||
	XRestrict     int    `json:"xRestrict"`
 | 
			
		||||
	Sl            int    `json:"sl"`
 | 
			
		||||
	URL           string `json:"url"`
 | 
			
		||||
	Pages         []IllustPage
 | 
			
		||||
	URLs          struct {
 | 
			
		||||
		Mini     string `json:"mini"`
 | 
			
		||||
		Thumb    string `json:"thumb"`
 | 
			
		||||
		Small    string `json:"small"`
 | 
			
		||||
		Regular  string `json:"regular"`
 | 
			
		||||
		Original string `json:"original"`
 | 
			
		||||
	} `json:"urls"`
 | 
			
		||||
	Description string `json:"description"`
 | 
			
		||||
	Tags        struct {
 | 
			
		||||
		AuthorID string      `json:"authorId"`
 | 
			
		||||
		IsLocked bool        `json:"isLocked"`
 | 
			
		||||
		Tags     []IllustTag `json:"tags"`
 | 
			
		||||
		Writable bool        `json:"writable"`
 | 
			
		||||
	} `json:"tags,omitempty"`
 | 
			
		||||
	UserID                  string `json:"userId"`
 | 
			
		||||
	UserName                string `json:"userName"`
 | 
			
		||||
	UserAccount             string `json:"userAccount"`
 | 
			
		||||
	Width                   int    `json:"width"`
 | 
			
		||||
	Height                  int    `json:"height"`
 | 
			
		||||
	PageCount               int    `json:"pageCount"`
 | 
			
		||||
	IsBookmarkable          bool   `json:"isBookmarkable"`
 | 
			
		||||
	Alt                     string `json:"alt"`
 | 
			
		||||
	IsAdContainer           bool   `json:"isAdContainer"`
 | 
			
		||||
	TitleCaptionTranslation struct {
 | 
			
		||||
		WorkTitle   string `json:"workTitle"`
 | 
			
		||||
		WorkCaption string `json:"workCaption"`
 | 
			
		||||
	} `json:"titleCaptionTranslation"`
 | 
			
		||||
	CreateDate      string `json:"createDate"`
 | 
			
		||||
	UpdateDate      string `json:"updateDate"`
 | 
			
		||||
	IsUnlisted      bool   `json:"isUnlisted"`
 | 
			
		||||
	ProfileImageURL string `json:"profileImageUrl"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//IllustTag .
 | 
			
		||||
type IllustTag struct {
 | 
			
		||||
	Tag         string `json:"tag"`
 | 
			
		||||
	Locked      bool   `json:"locked"`
 | 
			
		||||
	Deletable   bool   `json:"deletable"`
 | 
			
		||||
	UserID      string `json:"userId"`
 | 
			
		||||
	UserName    string `json:"userName"`
 | 
			
		||||
	Romaji      string `json:"romaji"`
 | 
			
		||||
	Translation struct {
 | 
			
		||||
		En string `json:"en"`
 | 
			
		||||
	} `json:"translation"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//IllustPage .
 | 
			
		||||
type IllustPage struct {
 | 
			
		||||
	URLs struct {
 | 
			
		||||
		Mini     string `json:"mini"`
 | 
			
		||||
		Thumb    string `json:"thumb"`
 | 
			
		||||
		Small    string `json:"small"`
 | 
			
		||||
		Regular  string `json:"regular"`
 | 
			
		||||
		Original string `json:"original"`
 | 
			
		||||
	} `json:"urls"`
 | 
			
		||||
	Width  int `json:"width"`
 | 
			
		||||
	Height int `json:"height"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//User .
 | 
			
		||||
type User struct {
 | 
			
		||||
	UserID          string `json:"userId"`
 | 
			
		||||
	UserName        string `json:"userName"`
 | 
			
		||||
	ProfileImageURL string `json:"profileImageUrl"`
 | 
			
		||||
	Following       bool   `json:"following"`
 | 
			
		||||
	Followed        bool   `json:"followed"`
 | 
			
		||||
	illusts         []Illust
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user