Groups implementation (alpha)

This commit is contained in:
lost+skunk 2024-04-16 00:19:37 +03:00
parent ab662f414c
commit 28d8653464
18 changed files with 318 additions and 133 deletions

View File

@ -36,6 +36,7 @@ func main() {
e, p := endpoint(r.URL.Path)
c := make(chan string, 100)
// some args
page, _ := strconv.ParseInt(r.URL.Query().Get("p"), 10, 32)
q := url.QueryEscape(r.URL.Query().Get("q"))
@ -43,6 +44,9 @@ func main() {
w.Header().Set("Content-Location", util.Conf.Base_uri)
}
action := r.URL.Query().Get("a")
// uri
switch e {
case "image":
fmt.Fprintln(w, misc.Getimage(p, url.QueryEscape(r.URL.Query().Get("t"))))
@ -59,10 +63,10 @@ func main() {
fmt.Fprintln(w, misc.Misc(strings.ToLower(p), true))
case "group":
fmt.Fprintln(w, "Groups is not implemented yet :(")
fmt.Fprintln(w, misc.GetGroup(action, r.URL.Query().Get("folder"), p, int(page)))
case "user":
fmt.Fprintln(w, user.Get(p, r.URL.Query().Get("a"), q, int(page)))
fmt.Fprintln(w, user.Get(p, action, q, int(page)))
case "post":
go post.Get(p, int(page)+1, c)

81
misc/groups.go Normal file
View File

@ -0,0 +1,81 @@
package misc
import (
"encoding/json"
"skunkyart/post"
"skunkyart/user"
"skunkyart/util"
"strconv"
)
func GetGroup(action, folderid, name string, page int) string {
switch action {
case "":
return about(name, page)
case "gallery":
f := getfolders(&name)
if folderid != "" {
var j struct {
Results []util.Deviation
}
rjs := util.Puppy("dashared/gallection/contents?username=" + name + "&type=gallery&offset=" + strconv.Itoa(50*page) + "&limit=50&folderid=" + folderid)
json.Unmarshal([]byte(rjs), &j)
return util.BaseList("templates/search.htm", "&a=gallery&folder="+folderid, "group/"+name, j.Results, page, f)
} else {
var c = make(chan string, 10)
if page < 1 {
page++
}
go user.Gallery(&name, c, strconv.Itoa(page), f)
return <-c
}
}
return ""
}
func getfolders(name *string) string {
var j util.AB
rjs := util.Puppy("dauserprofile/init/gallery?username=" + *name + "&deviations_limit=0&with_subfolders=true")
json.Unmarshal([]byte(rjs), &j)
var folders string
for _, a := range j.Gruser.Page.Modules {
for _, a := range a.ModuleData.Folders.Results {
folders += "<a href=\"" + util.Conf.Base_uri + "group/" + *name + "?a=gallery&folder=" + strconv.Itoa(a.FolderId) + "\">" + a.Name + "</a> "
}
}
return folders
}
func about(name string, page int) string {
var tmp struct {
Name, Description, Foundation, Status, Comments, Bg, Bgname string
V, P int
}
var j util.AB
rjs := util.Puppy("dauserprofile/init/about?username=" + name)
json.Unmarshal([]byte(rjs), &j)
tmp.Name = j.Owner.Username
tmp.Status = j.PageExtraData.GruserTagline
uid := make([]string, 1)
uid[0] = strconv.Itoa(j.Gruser.GruserId)
tmp.Comments = *post.GetComments(util.Conf.Base_uri+"group/"+tmp.Name, "", page+1, 4, uid)
for _, a := range j.Gruser.Page.Modules {
if a.ModuleData.GroupAbout.FoundationTs.Unix() > 0 {
tmp.Foundation = a.ModuleData.GroupAbout.FoundationTs.UTC().String()
}
if a.ModuleData.GroupAbout.Description.Html.Markup != "" {
tmp.Description += util.ParseDescription(a.ModuleData.GroupAbout.Description)
}
tmp.Bg = util.Images(a.ModuleData.CoverDeviation.CoverDeviation, a.ModuleData.CoverDeviation.CoverDeviation.Media, true)
tmp.Bgname = a.ModuleData.CoverDeviation.CoverDeviation.Title
}
tmp.V = j.PageExtraData.Stats.Watchers
tmp.P = j.PageExtraData.Stats.Pageviews
return util.TmpExec("templates/group.htm", &tmp)
}

View File

@ -59,5 +59,5 @@ func Search(q, p, scope string, output chan string) {
} else {
output <- "Missing query."
}
output <- util.TmpExec("templates/search/search.htm", &tmp)
output <- util.TmpExec("templates/search.htm", &tmp)
}

View File

@ -40,7 +40,7 @@ func js(c string, cc int, id []string, t int) (*string, bool, bool) {
for x := 0; x < cc; x++ {
/*
1: comments of the post;
4: comments on userpage
4: comments on userpage or group
*/
p := "dashared/comments/thread?typeid=" + strconv.Itoa(t) + "&itemid=" + id[len(id)-1] + "&maxdepth=1000&order=newest"
@ -121,16 +121,15 @@ func GetComments(uri, cursor string, page, typ int, id []string) *string {
// если комментариев больше, чем 0, то отображаем их, иначе пишем, что комментов нет.
if comments.Total > 0 {
htm = "<h2 id=\"comments\">Comments (" + strconv.Itoa(comments.Total) + ")</h2>" + htm
uri = uri[strings.LastIndex(uri, "/")+1:]
htm = "<details><summary><b>Comments (" + strconv.Itoa(comments.Total) + ")</b></summary>" + htm
// uri = uri[strings.LastIndex(uri, "/")+1:]
if prev {
htm += "<a href=\"" + uri + "?p=" + strconv.Itoa(page-2) + "#comments\"><-- Back</a> "
}
if next {
htm += "<a href=\"" + uri + "?p=" + strconv.Itoa(page) + "#comments\">Next --></a>"
}
} else {
htm = "<p>There is no comments.</p>"
htm += "</details>"
}
return &htm

View File

@ -46,38 +46,16 @@ func _post(id []string, author string, url string, page int) string {
tmp.Img = util.Images(j.Deviation, j.Deviation.Media, true)
if j.Deviation.Extended.DescriptionText.Html.Markup != "" {
tmp.Description = util.ParseDescription(j.Deviation.Extended.DescriptionText)
} else {
tmp.Description = util.ParseDescription(j.Deviation.TextContent)
}
tmp.Time = j.Deviation.PublishedTime.UTC().String()
tmp.Views = j.Deviation.Stats.Views
tmp.FavsCount = j.Deviation.Stats.Favourites
if j.Deviation.Extended.DescriptionText.Html.Markup != "" {
tmp.Description = j.Deviation.Extended.DescriptionText.Html.Markup
} else {
tmp.Description = j.Deviation.TextContent.Html.Markup
}
if len(tmp.Description) > 0 {
if tmp.Description[0:1] == "{" {
var j2 struct {
Blocks []struct {
Text string
}
}
json.Unmarshal([]byte(tmp.Description), &j2)
tmp.Description = ""
for _, a := range j2.Blocks {
if j.Deviation.TextContent.Html.Type == "draft" || j.Deviation.Extended.DescriptionText.Html.Type == "draft" {
tmp.Description += a.Text + "<br>"
} else {
tmp.Description = a.Text
}
}
}
tmp.Description = util.Parse(tmp.Description)
}
tmp.Downloads = j.Deviation.Stats.Downloads
tmp.Ai = j.Deviation.IsAiGenerated
tmp.License = j.Deviation.License

View File

@ -7,6 +7,10 @@ a {
text-decoration: none;
color: cadetblue;
}
a:hover {
color: red;
transition: 400ms;
}
form input, button, select {
background-color: #134134;
padding: 5px;
@ -38,7 +42,6 @@ form input, button, select {
color: rgb(160, 0, 147);
}
.content {
background-color: #001624;
border-radius: 3px;
display: flex;
flex-wrap: wrap;

24
templates/group.htm Normal file
View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
!BAZE!
<title>{{.Name}} | SkunkyArt</title>
<link rel="stylesheet" href="static/base.css">
</head>
<body>
{{if (ne .Bg "no")}}
<img src="{{.Bg}}" width="30%" title="{{.Bgname}}">
{{end}}
<h1><img src="avatar/{{.Name}}" width="60px">{{.Name}}</h1>
<h2><a href="group/{{.Name}}?a=gallery">Gallery</a></h2>
<p>Watchers: {{.V}}; Pageviews: {{.P}}</p>
<p>Group has been foundated in {{.Foundation}}</p>
<p><i title="Group caption">{{.Status}}</i></p>
<h2>About the group</h2>
<p>{{.Description}}</p>
{{.Comments}}
</body>
</html>

View File

@ -20,7 +20,7 @@
<span><strong><a href="user/{{.Author}}">{{.Author}}</a></strong> — {{if (.DD)}}
<span class="dd" title="Daily Deviation!"><b>{{.Postname}}</b></span>
{{else}}{{.Postname}}{{end}}
{{if (ne .License "none")}}({{.License}}){{end}} {{if (.Ai)}}[🤖]{{end}}
{{if (ne .License "none")}}<mark title="License">{{.License}}</mark>{{end}} {{if (.Ai)}}[🤖]{{end}}
{{if (.Nsfw)}}[<span class="nsfw">NSFW</span>]{{end}}
</span>
<br>
@ -39,10 +39,13 @@
<figcaption>{{.Description}}</figcaption>
{{end}}
{{if (ne .Recomendations "")}}
<h2>See also:</h2>
<div class="content">
{{.Recomendations}}
</div>
<br>
<details>
<summary><b>See also</b></summary>
<div class="content">
{{.Recomendations}}
</div>
</details>
{{end}}
{{.Comments}}
</figure>

View File

@ -13,6 +13,10 @@
<button type="submit">Search!</button>
</form> <a href="user/{{.Name}}">Home</a>
</h2>
{{if (ne .Folders "")}}
<p>Folders: {{.Folders}}</p>
{{end}}
<div class="content">
{{.Posts}}

View File

@ -1,4 +1,5 @@
Нужно сделать:
- рефакторинг
- провести оптимизацию кода
- кеширование жсона
- ~~реализовать работу на определённом пути (https://example.com/skunkyart)~~

View File

@ -19,7 +19,7 @@ func about(name *string, page int, output chan string) {
{
var tmp Tmp
var j ab
var j util.AB
// парсинг
rawjson := util.Puppy("dauserprofile/init/about?username=" + *name)
@ -105,6 +105,6 @@ func about(name *string, page int, output chan string) {
tmp.Comments = *post.GetComments("user/"+tmp.Name, "", page+1, 4, uid)
}
output <- util.TmpExec("templates/user/info.htm", tmp)
output <- util.TmpExec("templates/user/info.htm", &tmp)
}
}

View File

@ -6,11 +6,11 @@ import (
"strconv"
)
func gallery(name *string, output chan string, page string) {
func Gallery(name *string, output chan string, page string, folders ...string) {
{
var tmp struct {
Posts, Name, Nav string
TP int
Posts, Name, Nav, Folders string
TP int
}
var j struct {
Gruser struct {
@ -27,6 +27,9 @@ func gallery(name *string, output chan string, page string) {
}
}
}
Owner struct {
IsGroup bool
}
}
rawjson := util.Puppy("dauserprofile/init/gallery?username=" + *name + "&page=" + page + "&deviations_limit=50&with_subfolders=false")
@ -51,8 +54,16 @@ func gallery(name *string, output chan string, page string) {
}
tmp.Nav = ""
path := "user/"
if j.Owner.IsGroup {
path = "group/"
}
for x := 0; x < tmp.TP; x++ {
tmp.Nav += "<a href=\"" + util.Conf.Base_uri + "user/" + tmp.Name + "?a=gallery&p=" + strconv.Itoa(x+1) + "\">" + strconv.Itoa(x+1) + "</a> "
tmp.Nav += "<a href=\"" + util.Conf.Base_uri + path + tmp.Name + "?a=gallery&p=" + strconv.Itoa(x+1) + "\">" + strconv.Itoa(x+1) + "</a> "
}
for _, a := range folders {
tmp.Folders = a
}
}
output <- util.TmpExec("templates/user/gallery.htm", &tmp)

View File

@ -1,6 +1,9 @@
package user
import "strconv"
import (
"encoding/json"
"strconv"
)
func Get(name, action, query string, page int) string {
c := make(chan string, 100)
@ -13,9 +16,33 @@ func Get(name, action, query string, page int) string {
page = 1
}
go gallery(&name, c, strconv.Itoa(page))
go Gallery(&name, c, strconv.Itoa(page))
case "search":
go search(&name, &query, page, c)
}
return <-c
}
func rerror(err *string) string {
if len(*err) < 100 {
var j struct {
ErrorDescription string
}
json.Unmarshal([]byte(*err), &j)
switch j.ErrorDescription {
case "User deactivated.":
return "User deactivated their account or has been banned."
case "user_not_found.":
return "Not exists user."
default:
if *err == "Something went wrong. Status: 403" {
return "Rate limit from CloudFront."
} else {
return "Something went wrong."
}
}
}
return ""
}

View File

@ -1,72 +0,0 @@
package user
import (
"encoding/json"
"skunkyart/util"
)
type ab struct {
ErrorDescription string
Owner struct {
Username string
}
Gruser struct {
GruserId int
Page struct {
Modules []struct {
Name string
ModuleData struct {
About struct {
Country, Website, WebsiteLabel, Gender, Tagline string
DeviantFor int64
SocialLinks []struct {
Value string
}
TextContent struct {
Excerpt string
Html struct {
Markup string
}
}
Interests []struct {
Label, Value string
}
}
CoverDeviation struct {
CoverDeviation util.Deviation
}
}
}
}
}
PageExtraData struct {
GruserTagline string
Stats struct {
Deviations, Watchers, Watching, Pageviews, CommentsReceivedProfile, CommentsMade, Favourites, Friends int
}
}
}
func rerror(err *string) string {
if len(*err) < 100 {
var j struct {
ErrorDescription string
}
json.Unmarshal([]byte(*err), &j)
switch j.ErrorDescription {
case "User deactivated.":
return "User deactivated their account or has been banned."
case "user_not_found.":
return "Not exists user."
default:
if *err == "Something went wrong. Status: 403" {
return "Rate limit from CloudFront."
} else {
return "Something went wrong."
}
}
}
return ""
}

View File

@ -1,6 +1,7 @@
package util
import (
"encoding/json"
"strconv"
"strings"
"time"
@ -21,16 +22,16 @@ type Deviation struct {
Tags []struct {
Name string
}
DescriptionText struct {
Html HTML
}
RelatedContent []struct {
DescriptionText tx
RelatedContent []struct {
Deviations []Deviation
}
}
TextContent struct {
Html HTML
}
TextContent tx
}
type tx struct {
Html HTML
}
type Media struct {
@ -103,16 +104,72 @@ func Images(deviation Deviation, media Media, nfmt bool) string {
}
switch {
case deviation.IsAiGenerated:
deviation.Title += " [🤖]"
case deviation.IsDailyDeviation:
deviation.Title += " [<span class=\"dd\">DD</span>]"
case deviation.IsMature:
if !Conf.Nsfw {
return ""
}
deviation.Title += " [<span class=\"nsfw\">NSFW</span>]"
case deviation.IsAiGenerated:
deviation.Title += " [🤖]"
case deviation.IsDailyDeviation:
deviation.Title += " [<span class=\"dd\">DD</span>]"
}
return "<div class=\"block\">" + image + "<br><a href=\"" + Conf.Base_uri + "post" + link + "\">" + deviation.Author.Username + deviation.Title + "</a></div>"
}
func ParseDescription(tx tx) string {
var description string
ds := tx.Html.Markup
if len(ds) > 0 {
if ds[0:1] == "{" {
var j2 struct {
Blocks []struct {
Text string
}
}
json.Unmarshal([]byte(ds), &j2)
for _, a := range j2.Blocks {
if ds == "draft" {
ds += a.Text + "<br>"
} else {
ds = a.Text
}
}
}
description = Parse(ds)
if len(description) > 1000 {
tds := description[:1000]
description = "<details><summary>" + tds + "</summary>" + tds[1000:] + "</details>"
}
return description
}
return "No description."
}
func BaseList(template, args, uri string, results []Deviation, page int, folders ...string) string {
var tmp struct {
Results, Pages, Folders string
Total int
}
for _, a := range folders {
tmp.Folders = a
}
for _, a := range results {
tmp.Results += Images(a, a.Media, false)
}
if page > 0 {
tmp.Pages += "<a href=\"" + Conf.Base_uri + uri + "?p=" + strconv.Itoa(page-1) + args + "\"><-- Back</a> "
}
tmp.Pages += "<a href=\"" + Conf.Base_uri + uri + "?p=" + strconv.Itoa(page+1) + args + "\">Next --></a>"
return TmpExec(template, &tmp)
}

65
util/grjunk.go Normal file
View File

@ -0,0 +1,65 @@
package util
type AB struct {
ErrorDescription string
Owner struct {
Username string
}
Gruser struct {
GruserId int
Page struct {
Modules []struct {
Name string
ModuleData struct {
About struct {
Country, Website, WebsiteLabel, Gender, Tagline string
DeviantFor int64
SocialLinks []struct {
Value string
}
TextContent Description
Interests []struct {
Label, Value string
}
}
CoverDeviation struct {
CoverDeviation Deviation
}
// группы
GroupAbout struct {
Tagline string
FoundationTs Time
Description struct {
Html HTML
}
}
GroupAdmins struct {
Results []struct {
Username string
}
}
Folders struct {
Results []struct {
FolderId int
Name string
}
}
}
}
}
}
PageExtraData struct {
GruserTagline string
Stats struct {
Deviations, Watchers, Watching, Pageviews, CommentsReceivedProfile, CommentsMade, Favourites, Friends int
}
}
}
type Description struct {
Excerpt string
Html struct {
Markup string
}
}