krz/devianter

A DeviantArt guest API library for Go.

clone: git clone https://gitbay.org/krz/devianter.git

9b850886656bb2ecf192e6d9df63ea07d175de06

unsigned

author: lost+skunk <skunky@macaw.me> · 2024-06-05T11:32:40Z

User implementation and particaly groups
 comments.go       | 21 ++++++-------
 deviantion.go     | 19 +++++++-----
 examples/post.go  | 25 ---------------
 implementation.md |  2 ++
 misc.go           | 49 ++++++++++++++++++++---------
 todo.md           |  5 ++-
 user-group.go     | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 152 insertions(+), 61 deletions(-)

diff --git a/comments.go b/comments.go
index f6a86c6..7b3bb3d 100644
--- a/comments.go
+++ b/comments.go
@@ -13,24 +13,21 @@ type comments struct {
 
 	Total  int
 	Thread []struct {
-		CommentId, ParentId, Replies, Likes int
-		Posted                              time
-		IsAuthorHighlited                   bool
+		Replies, Likes int
+		ID             int `json:"commentId"`
+		Parent         int `json:"ParrentId"`
 
-		Desctiption string
+		Posted time
+		Author bool `json:"isAuthorHighlited"`
 
-		// упрощение структуры с комментами
-		Comment string
+		Desctiption string
+		Comment     string
 
-		TextContent struct {
-			Html struct {
-				Markup string
-			}
-		}
+		TextContent text
 
 		User struct {
 			Username string
-			IsBanned bool
+			Banned   bool `json:"isBanned"`
 		}
 	}
 }
diff --git a/deviantion.go b/deviantion.go
index 1f6644c..9803855 100644
--- a/deviantion.go
+++ b/deviantion.go
@@ -21,10 +21,14 @@ func (t *time) UnmarshalJSON(b []byte) (err error) {
 
 // самая главная структура для поста
 type deviantion struct {
-	Title, Url, License                       string
-	PublishedTime                             time
-	IsMature, IsAiGenerated, IsDailyDeviation bool
-	Author                                    struct {
+	Title, Url, License string
+	PublishedTime       time
+
+	NSFW bool `json:"isMature"`
+	AI   bool `json:"isAiGenerated"`
+	DD   bool `json:"isDailyDeviation"`
+
+	Author struct {
 		Username string
 	}
 	Stats struct {
@@ -54,11 +58,13 @@ type media struct {
 }
 
 type text struct {
-	Html struct {
+	Excerpt string
+	Html    struct {
 		Markup, Type string
 	}
 }
 
+// структура поста
 type Deviantion struct {
 	Deviation deviantion
 	Comments  struct {
@@ -73,7 +79,6 @@ type Deviantion struct {
 	}
 
 	IMG, Desctiption string
-	Recomendations   []deviantion
 }
 
 // для работы функции нужно ID поста и имя пользователя.
@@ -98,7 +103,7 @@ func Deviation(id string, user string) Deviantion {
 
 	// базовая обработка описания
 	txt := st.Deviation.TextContent.Html.Markup
-	if len(txt) > 0 && txt[0:1] == "{" {
+	if len(txt) > 0 && txt[1] == 125 {
 		var description struct {
 			Blocks []struct {
 				Text string
diff --git a/examples/post.go b/examples/post.go
deleted file mode 100644
index 2789c46..0000000
--- a/examples/post.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package main
-
-import (
-	"git.macaw.me/skunky/devianter"
-)
-
-func main() {
-	id := "973578309"
-	d := devianter.Deviation(id, "Thrumyeye")
-
-	println("Post Name:", d.Deviation.Title, "\nIMG url:", d.IMG)
-
-	c := devianter.Comments(id, "", 0, 1)
-	println("\n\nPost Comments:", c.Total)
-
-	for _, a := range c.Thread {
-		if a.User.IsBanned {
-			a.User.Username += " [v bane]"
-		}
-		println(a.User.Username+":", a.Comment)
-	}
-
-	search := devianter.Search("skunk", "2", 'a')
-	println(search.Total, search.Pages)
-}
diff --git a/implementation.md b/implementation.md
index 3f1c58a..45d9ec8 100644
--- a/implementation.md
+++ b/implementation.md
@@ -2,3 +2,5 @@
 - emojis
 - deviantions
 - comments
+- search (including gallery search)
+- users (with gallery)
diff --git a/misc.go b/misc.go
index c847e44..d5f6793 100644
--- a/misc.go
+++ b/misc.go
@@ -3,11 +3,11 @@ package devianter
 import (
 	"encoding/json"
 	"errors"
-	"fmt"
 	"io"
 	"log"
 	"math"
 	"net/http"
+	"strconv"
 	"strings"
 )
 
@@ -117,27 +117,44 @@ func AEmedia(name string, t rune) (string, error) {
 
 /* SEARCH */
 type search struct {
-	Total      int `json:"estTotal"`
-	Pages      int // only for 'a' scope.
-	Deviations []deviantion
+	Total   int          `json:"estTotal"`
+	Pages   int          // only for 'a' and 'g' scope.
+	Results []deviantion `json:"deviations,results"`
 }
 
-func Search(query, page string, scope rune) (ss search) {
+func Search(query string, page int, scope rune, user ...string) (ss search, e error) {
 	var url strings.Builder
+	e = nil
 
 	// о5 построение ссылок.
 	switch scope {
-	case 'a':
+	case 'a': // поиск артов по названию
 		url.WriteString("dabrowse/search/all?q=")
-	case 't':
+	case 't': // поиск артов по тегам
 		url.WriteString("dabrowse/networkbar/tag/deviations?tag=")
+	case 'g': // поиск артов пользователя или группы
+		if user != nil {
+			url.WriteString("dashared/gallection/search?username=")
+			for _, a := range user {
+				url.WriteString(a)
+			}
+			url.WriteString("&type=gallery&order=most-recent&init=true&limit=50&q=")
+		} else {
+			e = errors.New("Missing username (last argument)")
+			return
+		}
 	default:
-		log.Fatalln("Invalid type.\n- 'a' -- all;\n- 't' -- tag.")
+		log.Fatalln("Invalid type.\n- 'a' -- all;\n- 't' -- tag;\n- 'g' - gallery.")
 	}
 
 	url.WriteString(query)
-	url.WriteString("&page=")
-	url.WriteString(page)
+	if scope != 'g' { // если область поиска не равна поиску по группам, то активируется этот код
+		url.WriteString("&page=")
+	} else { // иначе вместо страницы будет оффсет и страница умножится на 50
+		url.WriteString("&offset=")
+		page = 50 * page
+	}
+	url.WriteString(strconv.Itoa(page))
 
 	ujson(url.String(), &ss)
 
@@ -184,10 +201,14 @@ func puppy(data string) (string, error) {
 		}
 	}
 
-	body := request(
-		fmt.Sprintf("https://www.deviantart.com/_puppy/%s&csrf_token=%s&da_minor_version=20230710", data, token),
-		cookie,
-	)
+	var url strings.Builder
+	url.WriteString("https://www.deviantart.com/_puppy/")
+	url.WriteString(data)
+	url.WriteString("&csrf_token=")
+	url.WriteString(token)
+	url.WriteString("&da_minor_version=20230710")
+
+	body := request(url.String(), cookie)
 
 	// если код ответа не 200, возвращается ошибка
 	if body.Status != 200 {
diff --git a/todo.md b/todo.md
index 0648437..db45d13 100644
--- a/todo.md
+++ b/todo.md
@@ -1,3 +1,2 @@
-- ~~users~~
-- ~~groups~~
-- ~~images in comments~~
\ No newline at end of file
+- groups
+- images in comments
\ No newline at end of file
diff --git a/user-group.go b/user-group.go
new file mode 100644
index 0000000..32342fb
--- /dev/null
+++ b/user-group.go
@@ -0,0 +1,92 @@
+package devianter
+
+import (
+	"strconv"
+	"strings"
+)
+
+// структура группы или пользователя
+type Group struct {
+	ErrorDescription string
+	Owner            struct {
+		Group    bool `json:"isGroup"`
+		Username string
+	}
+	Gruser struct {
+		ID   int `json:"gruserId"`
+		Page struct {
+			Modules []struct {
+				Name       string
+				ModuleData struct {
+					About struct {
+						Country, Website, WebsiteLabel, Gender, Tagline string
+						DeviantFor                                      int64
+						SocialLinks                                     []struct {
+							Value string
+						}
+						TextContent text
+						Interests   []struct {
+							Label, Value string
+						}
+					}
+					CoverDeviation struct {
+						Deviation deviantion `json:"coverDeviation"`
+					}
+
+					// группы
+					GroupAbout struct {
+						Tagline     string
+						CreatinDate time `json:"foundationTs"`
+						Description text
+					}
+					GroupAdmins struct {
+						Results []struct {
+							Username string
+						}
+					}
+					Folders struct {
+						Results []struct {
+							FolderId int
+							Name     string
+						}
+					}
+
+					// галерея
+					ModuleData struct {
+						Folder struct {
+							Username   string
+							Pages      int `json:"totalPageCount"`
+							Deviations []deviantion
+						} `json:"folderDeviations"`
+					}
+				}
+			}
+		}
+	}
+	PageExtraData struct {
+		GruserTagline string
+		Stats         struct {
+			Deviations, Watchers, Watching, Pageviews, CommentsMade, Favourites, Friends int
+			FeedComments                                                                 int `json:"commentsReceivedProfile"`
+		}
+	}
+}
+
+func UGroup(name string) (g Group) {
+	ujson("dauserprofile/init/about?username="+name, &g)
+
+	return
+}
+
+// гарелея пользователя или группы
+func Gallery(name string, page int) (g Group) {
+	var url strings.Builder
+	url.WriteString("dauserprofile/init/gallery?username=")
+	url.WriteString(name)
+	url.WriteString("&page=")
+	url.WriteString(strconv.Itoa(page))
+	url.WriteString("&deviations_limit=50&with_subfolders=false")
+
+	ujson(url.String(), &g)
+	return
+}