krz/skunky-art

Alternative privacy frontend for DeviantArt.

clone: git clone https://gitbay.org/krz/skunky-art.git

v1.3.2: app/wrapper.go · raw

  1package app
  2
  3import (
  4	"regexp"
  5	"strconv"
  6	"strings"
  7	"time"
  8
  9	"git.macaw.me/skunky/devianter"
 10	"golang.org/x/net/html"
 11)
 12
 13func (s skunkyart) GRUser() {
 14	if len(s.Query) < 1 {
 15		s.ReturnHTTPError(400)
 16		return
 17	}
 18
 19	var g devianter.Group
 20	var daError devianter.Error
 21	g.Name = s.Query
 22	var err error
 23	s.Templates.GroupUser.GR, err, daError = g.Get()
 24	try(err)
 25	if daError.RAW != nil {
 26		s.Error(daError)
 27		return
 28	}
 29
 30	group := &s.Templates.GroupUser
 31
 32	switch s.Type {
 33	case 'a':
 34		g := group.GR
 35		s.Atom = false
 36		for _, x := range g.Gruser.Page.Modules {
 37			switch x.Name {
 38			case "about", "group_about":
 39				switch g.Owner.Group {
 40				case true:
 41					var about = &x.ModuleData.GroupAbout
 42					group.Group = true
 43					group.CreationDate = x.ModuleData.GroupAbout.FoundatedAt.UTC().String()
 44					group.About.DescriptionFormatted = ParseDescription(about.Description)
 45				case false:
 46					group.About.A = x.ModuleData.About
 47					var about = &group.About.A
 48					group.CreationDate = time.Unix(time.Now().Unix()-x.ModuleData.About.RegDate, 0).UTC().String()
 49					group.About.DescriptionFormatted = ParseDescription(about.Description)
 50
 51					for _, val := range x.ModuleData.About.SocialLinks {
 52						var social strings.Builder
 53						social.WriteString(`<a target="_blank" href="`)
 54						social.WriteString(val.Value)
 55						social.WriteString(`">`)
 56						social.WriteString(val.Value)
 57						social.WriteString("</a><br>")
 58						group.About.Social += social.String()
 59					}
 60
 61					for _, val := range x.ModuleData.About.Interests {
 62						var interest strings.Builder
 63						interest.WriteString(val.Label)
 64						interest.WriteString(": <b>")
 65						interest.WriteString(val.Value)
 66						interest.WriteString("</b><br>")
 67						group.About.Interests += interest.String()
 68					}
 69				}
 70				group.About.Comments = s.ParseComments(devianter.GetComments(strconv.Itoa(group.GR.Gruser.ID), "", s.Page, 4))
 71
 72			case "cover_deviation":
 73				group.About.BGMeta = x.ModuleData.CoverDeviation.Deviation
 74				group.About.BGMeta.Url = ConvertDeviantArtUrlToSkunkyArt(group.About.BGMeta.Url)
 75				group.About.BG = ParseMedia(group.About.BGMeta.Media)
 76			case "group_admins":
 77				var htm strings.Builder
 78				for _, z := range x.ModuleData.GroupAdmins.Results {
 79					htm.WriteString(BuildUserPlate(z.User.Username))
 80				}
 81				group.Admins += htm.String()
 82			}
 83
 84		}
 85	case 'g', 'f':
 86		var all bool
 87		var content devianter.Group
 88
 89		folderid, _ := strconv.Atoi(s.Args.Get("folder"))
 90
 91		if a := s.Args.Get("all"); a == "true" {
 92			all = true
 93		}
 94
 95		if s.Page == 0 {
 96			s.Page++
 97		}
 98
 99		if s.Type == 'f' {
100			content, daError = g.Favourites(s.Page, all, folderid)
101		} else {
102			content, err, daError = g.Gallery(s.Page, folderid)
103			try(err)
104		}
105
106		if daError.RAW != nil {
107			s.Error(daError)
108			return
109		}
110
111		if folderid > 0 || (s.Type == 'f' && all) {
112			group.Gallery.List = s.DeviationList(content.Content.Results, true, DeviationList{
113				More: content.Content.HasMore,
114			})
115		} else {
116			for _, x := range content.Content.Gruser.Page.Modules {
117				if l := len(x.ModuleData.Folders.Results); l != 0 {
118					var folders strings.Builder
119					folders.WriteString(`<h1 id="folders"><a href="#folder">#</a> Folders</h1><div class="folders"><br>`)
120					for _, x := range x.ModuleData.Folders.Results {
121						if x.FolderId != -1 && x.Size != 0 {
122							folders.WriteString(`<div class="block folder-item">`)
123
124							if !(x.Thumb.NSFW && !CFG.Nsfw) {
125								folders.WriteString(`<a href="`)
126								folders.WriteString(ConvertDeviantArtUrlToSkunkyArt(x.Thumb.Url))
127								folders.WriteString(`"><img loading="lazy" src="`)
128								folders.WriteString(ParseMedia(x.Thumb.Media))
129								folders.WriteString(`" title="`)
130								folders.WriteString(x.Thumb.Title)
131								folders.WriteString(`"></a>`)
132							} else {
133								folders.WriteString(`<h1>[ <span class="nsfw">NSFW</span> ]</h1>`)
134							}
135							folders.WriteString("<br>")
136
137							folders.WriteString(`<a href="group_user?folder=`)
138							folders.WriteString(strconv.Itoa(x.FolderId))
139							folders.WriteString("&q=")
140							folders.WriteString(s.Query)
141							folders.WriteString("&type=")
142							folders.WriteString(string(s.Type))
143							folders.WriteString(`">`)
144							folders.WriteString(x.Name)
145							folders.WriteString(`</a>`)
146
147							folders.WriteString("</div>")
148						}
149					}
150					folders.WriteString(`</div><h1 id="content"><a href="#content">#</a> Content</h1>`)
151					group.Gallery.Folders = folders.String()
152				}
153
154				if x.Name == "folder_deviations" {
155					group.Gallery.List = s.DeviationList(x.ModuleData.Folder.Deviations, true, DeviationList{
156						Pages: x.ModuleData.Folder.Pages,
157						More:  x.ModuleData.Folder.HasMore,
158					})
159				}
160			}
161		}
162	default:
163		s.ReturnHTTPError(400)
164	}
165
166	if !s.Atom {
167		s.ExecuteTemplate("gruser.htm", "html", &s)
168	}
169}
170
171// посты
172func (s skunkyart) Deviation(author, postname string) {
173	id_search := regexp.MustCompile("[0-9]+").FindAllString(postname, -1)
174	if len(id_search) < 1 {
175		s.ReturnHTTPError(400)
176		return
177	}
178
179	var err devianter.Error
180	post := &s.Templates.Deviation
181
182	id := id_search[len(id_search)-1]
183	post.Post, err = devianter.GetDeviation(id, author)
184	if err.RAW != nil {
185		s.Error(err)
186		return
187	}
188
189	if post.Post.Comments.Total <= 50 {
190		post.Post.Comments.Cursor = ""
191	}
192
193	if post.Post.Deviation.TextContent.Excerpt != "" {
194		post.Post.Description = ParseDescription(post.Post.Deviation.TextContent)
195	} else {
196		post.Post.Description = ParseDescription(post.Post.Deviation.Extended.DescriptionText)
197	}
198
199	for _, x := range post.Post.Deviation.Extended.RelatedContent {
200		if len(x.Deviations) != 0 {
201			post.Related += s.DeviationList(x.Deviations, false)
202		}
203	}
204
205	// хештэги
206	for _, x := range post.Post.Deviation.Extended.Tags {
207		var tag strings.Builder
208		tag.WriteString(` <a href="`)
209		tag.WriteString(UrlBuilder("search", "?q=", x.Name, "&type=tag"))
210		tag.WriteString(`">#`)
211		tag.WriteString(x.Name)
212		tag.WriteString("</a>")
213
214		post.Tags += tag.String()
215	}
216
217	post.Comments = s.ParseComments(devianter.GetComments(id, post.Post.Comments.Cursor, s.Page, 1))
218	post.StringTime = post.Post.Deviation.PublishedTime.UTC().String()
219	post.Post.IMG = ParseMedia(post.Post.Deviation.Media)
220
221	s.ExecuteTemplate("deviantion.htm", "html", &s)
222}
223
224func (s skunkyart) DD() {
225	dd, err := devianter.GetDailyDeviations(s.Page)
226	if err.RAW != nil {
227		s.Error(err)
228		return
229	}
230	var strips strings.Builder
231	for _, x := range dd.Strips {
232		strips.WriteString(`<h3 class="`)
233		strips.WriteString(x.Codename)
234		strips.WriteString(`"> <a href="#`)
235		strips.WriteString(x.Codename)
236		strips.WriteString(`"># </a>`)
237		strips.WriteString(x.Title)
238		strips.WriteString(`</h3>`)
239
240		strips.WriteString(s.DeviationList(x.Deviations, false))
241	}
242	s.Templates.DDStrips = strips.String()
243	s.Templates.SomeList = s.DeviationList(dd.Deviations, true, DeviationList{
244		Pages: 0,
245		More:  dd.HasMore,
246	})
247	if !s.Atom {
248		s.ExecuteTemplate("daily.htm", "html", &s)
249	}
250}
251
252func (s skunkyart) Search() {
253	if s.Query == "" {
254		s.ReturnHTTPError(400)
255		return
256	}
257
258	var err error
259	var daError devianter.Error
260	ss := &s.Templates.Search
261	switch s.Type {
262	case 'a', 't':
263		ss.Content, err, daError = devianter.PerformSearch(s.Query, s.Page, s.Type)
264	case 'g', 'f':
265		ss.Content, err, daError = devianter.PerformSearch(s.Query, s.Page, s.Type, s.Args.Get("usr"))
266	case 'r': // скраппер, поскольку девиантартовцы зажопили гостевое API для поиска групп
267		var (
268			usernames = make(map[int]string)
269			url       strings.Builder
270			num       int
271		)
272
273		s.Page++
274
275		url.WriteString("https://www.deviantart.com/groups/?q=")
276		url.WriteString(s.Query)
277		if s.Page > 1 {
278			url.WriteString("&offset=")
279			url.WriteString(strconv.Itoa(10 * s.Page))
280		}
281
282		dwnld := Download(url.String())
283
284		for z := html.NewTokenizer(strings.NewReader(string(dwnld.Body))); ; {
285			if n, token := z.Next(), z.Token(); n == html.StartTagToken && token.Data == "a" {
286				for _, x := range token.Attr {
287					if x.Key == "class" && x.Val == "u regular username" {
288						usernames[num] = GetValueOfTag(z)
289						num++
290					}
291				}
292			} else if n == 0 {
293				break
294			} else {
295				continue
296			}
297		}
298
299		if l := len(usernames); l != 0 {
300			ss.List += `<div class="content plates">`
301			for x := 0; x < len(usernames); x++ {
302				ss.List += BuildUserPlate(usernames[x])
303			}
304			ss.List += `</div>`
305			ss.List += s.NavBase(DeviationList{
306				More: true,
307			})
308		}
309	default:
310		s.ReturnHTTPError(400)
311		return
312	}
313	try(err)
314
315	if s.Type != 'r' {
316		if daError.RAW != nil {
317			s.Error(daError)
318			return
319		}
320
321		ss.List = s.DeviationList(ss.Content.Results, false, DeviationList{
322			Pages: ss.Content.Pages,
323			More:  ss.Content.HasMore,
324		})
325	}
326
327	s.ExecuteTemplate("search.htm", "html", &s)
328}
329
330func (s skunkyart) Emojitar(name string) {
331	if name == "" || !(s.Type == 'a' || s.Type == 'e') {
332		s.ReturnHTTPError(400)
333		return
334	}
335
336	ae, e := devianter.AEmedia(name, s.Type)
337	if e != nil {
338		s.ReturnHTTPError(404)
339	}
340	wr(s.Writer, ae)
341}