mirror of
https://github.com/by-jp/www.byjp.me.git
synced 2025-08-10 19:05:41 +01:00
Add comments
This commit is contained in:
parent
50278343bc
commit
0953eb99a2
14 changed files with 193 additions and 19 deletions
|
@ -455,3 +455,61 @@ figure {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.interactions {
|
||||||
|
|
||||||
|
details {
|
||||||
|
|
||||||
|
summary {
|
||||||
|
cursor: pointer;
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
&::marker, &::-webkit-details-marker {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
summary::after {
|
||||||
|
color: var(--accent);
|
||||||
|
opacity: 0.8;
|
||||||
|
content: ' (show)';
|
||||||
|
}
|
||||||
|
&[open] summary {
|
||||||
|
&::after {
|
||||||
|
content: ' (hide)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.reactions {
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
&:not(:first-of-type) {
|
||||||
|
margin: auto 0 auto 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ol.comments {
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.muted {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
data/interactions/photos/mums-garden.json
Normal file
1
data/interactions/photos/mums-garden.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"interactions":[{"emoji":"⭐️","url":"https://pixelfed.social/p/jphastings/619856573800023125","author":{"name":"JP","url":"https://hachyderm.io/users/byjp"},"timestamp":"0001-01-01T00:00:00Z"},{"emoji":"⭐️","url":"https://pixelfed.social/p/jphastings/619856573800023125","author":{"name":"Ben!","url":"https://pixelfed.social/bencord0"},"timestamp":"0001-01-01T00:00:00Z"},{"emoji":"⭐️","url":"https://pixelfed.social/p/jphastings/619856573800023125","author":{"name":"Thomas Zimmermann","url":"https://pixelfed.social/curlingtom"},"timestamp":"0001-01-01T00:00:00Z"},{"emoji":"⭐️","url":"https://pixelfed.social/p/jphastings/619856573800023125","author":{"name":"Ivan Jurišić","url":"https://pixelfed.social/ijurisic"},"timestamp":"0001-01-01T00:00:00Z"}],"reactions":{"⭐️":4}}
|
|
@ -1 +0,0 @@
|
||||||
[{"emoji":"⭐️","author":{"name":"JP","url":"https://hachyderm.io/users/byjp"},"timestamp":"2022-12-14T11:16:00Z"},{"emoji":"⭐️","author":{"name":"Ben!","url":"https://pixelfed.social/bencord0"},"timestamp":"2019-09-14T08:43:33Z"},{"emoji":"⭐️","author":{"name":"Thomas Zimmermann","url":"https://pixelfed.social/curlingtom"},"timestamp":"2022-10-30T14:12:09Z"},{"emoji":"⭐️","author":{"name":"Ivan Jurišić","url":"https://pixelfed.social/ijurisic"},"timestamp":"2019-09-27T22:53:45Z"}]
|
|
1
data/interactions/photos/sunny-brunch.json
Normal file
1
data/interactions/photos/sunny-brunch.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"interactions":[{"emoji":"⭐️","url":"https://pixelfed.social/p/jphastings/629220605979255535","author":{"name":"Rui Almeida","url":"https://pixelfed.social/RJCA_PT"},"timestamp":"0001-01-01T00:00:00Z"}],"reactions":{"⭐️":1}}
|
|
@ -1 +0,0 @@
|
||||||
[{"emoji":"⭐️","author":{"name":"Rui Almeida","url":"https://pixelfed.social/RJCA_PT"},"timestamp":"2022-12-03T15:13:46Z"}]
|
|
57
layouts/partials/interactions.html
Normal file
57
layouts/partials/interactions.html
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
{{ $interactions := index .Site.Data.interactions (split (.Path | path.Dir) "/") }}
|
||||||
|
{{ with $interactions }}
|
||||||
|
<div class="interactions">
|
||||||
|
{{ $most := 0 }}
|
||||||
|
{{ $emoji := "" }}
|
||||||
|
{{ range $thisEm, $count := .reactions }}
|
||||||
|
{{ if gt $count $most }}
|
||||||
|
{{ $most = $count }}
|
||||||
|
{{ $emoji = $thisEm }}
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<details open>
|
||||||
|
<summary>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-message-circle"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>
|
||||||
|
|
||||||
|
Reactions & comments
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<ul class="reactions">
|
||||||
|
{{ range $thisEm, $count := .reactions }}
|
||||||
|
{{ if gt $count 0 }}
|
||||||
|
<li>
|
||||||
|
{{ if eq $thisEm "❤️" }}<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="lch(55% 71 27)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-heart"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path></svg>{{ end }}
|
||||||
|
{{ if eq $thisEm "⭐️" }}<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="lch(65% 71 81)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-star"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon></svg>{{ end }}
|
||||||
|
{{ if eq $thisEm "👍" }}<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="lch(55% 71 270)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-thumbs-up"><path d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"></path></svg>{{ end }}
|
||||||
|
{{ if eq $thisEm "🔁" }}<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="lch(55% 71 130)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-repeat"><polyline points="17 1 21 5 17 9"></polyline><path d="M3 11V9a4 4 0 0 1 4-4h14"></path><polyline points="7 23 3 19 7 15"></polyline><path d="M21 13v2a4 4 0 0 1-4 4H3"></path></svg>{{ end }}
|
||||||
|
{{ if eq $thisEm "💬" }}<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="lch(65% 0 0)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-message-circle"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>{{ end }}
|
||||||
|
|
||||||
|
{{ $count }}
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<ol class="comments">
|
||||||
|
{{ range .interactions }}
|
||||||
|
{{ if not .comment }}
|
||||||
|
{{ continue }}
|
||||||
|
{{ end }}
|
||||||
|
<li>
|
||||||
|
<a href="{{.author.url}}">{{ .author.name }}</a>: {{ .comment }}
|
||||||
|
<span class="muted">(<a href="{{.url }}">{{- partial "rel-date.html" (dict "time" .timestamp "rel" $.Page.Date) -}}</a>)</span>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
</ol>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
{{ else }}
|
||||||
|
<p>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-message-circle"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>
|
||||||
|
|
||||||
|
No comments or reactions
|
||||||
|
</p>
|
||||||
|
{{ end }}
|
14
layouts/partials/rel-date.html
Normal file
14
layouts/partials/rel-date.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{{- $desc := "0s" -}}
|
||||||
|
{{- $diff := (time .time).Sub (time .rel) -}}
|
||||||
|
{{- if gt $diff.Hours 168 -}}
|
||||||
|
{{- $desc = printf "%.0fw" (div $diff.Hours 168) -}}
|
||||||
|
{{- else if gt $diff.Hours 24 -}}
|
||||||
|
{{- $desc = printf "%.0fd" (div $diff.Hours 24) -}}
|
||||||
|
{{- else if gt $diff.Minutes 60 -}}
|
||||||
|
{{- $desc = printf "%.0fh" (div $diff.Minutes 60) -}}
|
||||||
|
{{- else if gt $diff.Seconds 60 -}}
|
||||||
|
{{- $desc = printf "%.0fm" (div $diff.Seconds 60) -}}
|
||||||
|
{{- else -}}
|
||||||
|
{{- $desc = printf "%.0fs" (div $diff.Seconds 1) -}}
|
||||||
|
{{- end -}}
|
||||||
|
<time timestamp="{{ .time }}" title="{{ time .time | dateFormat "2006-01-02 03:04 MST" }}">{{- $desc -}}</time>
|
|
@ -41,6 +41,8 @@
|
||||||
{{ dateFormat .Site.Params.dateformNumTime .Date }}
|
{{ dateFormat .Site.Params.dateformNumTime .Date }}
|
||||||
</date>
|
</date>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{{ partial "interactions.html" . }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
|
@ -53,17 +53,31 @@ func (b *backfeeder) BackfeedAll(toBackfeed ToBackfeedList) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeInteractions(dir string, ias []shared.Interaction) error {
|
func writeInteractions(dir string, ias []shared.Interaction) error {
|
||||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
if err := os.MkdirAll(filepath.Dir(dir), 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
path := filepath.Join(dir, "interactions.json")
|
path := dir + ".json"
|
||||||
|
|
||||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
enc := json.NewEncoder(f)
|
enc := json.NewEncoder(f)
|
||||||
return enc.Encode(ias)
|
|
||||||
|
split := map[string]interface{}{
|
||||||
|
"interactions": ias,
|
||||||
|
"reactions": make(map[string]int),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ia := range ias {
|
||||||
|
if ia.Emoji != "" {
|
||||||
|
split["reactions"].(map[string]int)[ia.Emoji]++
|
||||||
|
}
|
||||||
|
if ia.Comment != "" {
|
||||||
|
split["reactions"].(map[string]int)["💬"]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enc.Encode(split)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ type config struct {
|
||||||
syndicationMatchers map[string]*regexp.Regexp
|
syndicationMatchers map[string]*regexp.Regexp
|
||||||
urlToPublicPath func(string) string
|
urlToPublicPath func(string) string
|
||||||
urlToInteractionsPath func(string) string
|
urlToInteractionsPath func(string) string
|
||||||
|
|
||||||
|
performBackfeed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseConfig(cfgPath string) (*config, error) {
|
func parseConfig(cfgPath string) (*config, error) {
|
||||||
|
@ -50,12 +52,16 @@ func parseConfig(cfgPath string) (*config, error) {
|
||||||
feeds: []string{},
|
feeds: []string{},
|
||||||
services: services.New(),
|
services: services.New(),
|
||||||
syndicationMatchers: make(map[string]*regexp.Regexp),
|
syndicationMatchers: make(map[string]*regexp.Regexp),
|
||||||
|
performBackfeed: cfgData.InteractionsDir != "",
|
||||||
urlToPublicPath: func(url string) string {
|
urlToPublicPath: func(url string) string {
|
||||||
return path.Join(cfgData.PublishRoot, strings.TrimPrefix(url, cfgData.PublishURL))
|
return path.Join(cfgData.PublishRoot, strings.TrimPrefix(url, cfgData.PublishURL))
|
||||||
},
|
},
|
||||||
urlToInteractionsPath: func(url string) string {
|
}
|
||||||
|
|
||||||
|
if cfg.performBackfeed {
|
||||||
|
cfg.urlToInteractionsPath = func(url string) string {
|
||||||
return path.Join(cfgData.InteractionsDir, strings.TrimPrefix(url, cfgData.PublishURL))
|
return path.Join(cfgData.InteractionsDir, strings.TrimPrefix(url, cfgData.PublishURL))
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.content, err = doublestar.Glob(os.DirFS("."), cfgData.ContentGlob)
|
cfg.content, err = doublestar.Glob(os.DirFS("."), cfgData.ContentGlob)
|
||||||
|
@ -80,11 +86,14 @@ func parseConfig(cfgPath string) (*config, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
bf, err := svc.BackfeedMatcher()
|
if cfg.performBackfeed {
|
||||||
if err != nil {
|
bf, err := svc.BackfeedMatcher()
|
||||||
return nil, fmt.Errorf("cannot perform backfeed matching for '%s' because %w", name, err)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot perform backfeed matching for '%s' because %w", name, err)
|
||||||
|
}
|
||||||
|
cfg.syndicationMatchers[name] = bf
|
||||||
}
|
}
|
||||||
cfg.syndicationMatchers[name] = bf
|
|
||||||
serviceTags = append(serviceTags, name)
|
serviceTags = append(serviceTags, name)
|
||||||
}
|
}
|
||||||
cfg.tagMatcher, err = shared.TagMatcher(serviceTags)
|
cfg.tagMatcher, err = shared.TagMatcher(serviceTags)
|
||||||
|
|
|
@ -34,7 +34,7 @@ func main() {
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
if len(services) > 0 {
|
if len(services) > 0 {
|
||||||
fmt.Fprintf(os.Stderr, "Connecting to %s to syndicate & backfeed…\n", strings.Join(services, ", "))
|
fmt.Fprintf(os.Stderr, "Connecting to %s to syndicate…\n", strings.Join(services, ", "))
|
||||||
for _, sname := range services {
|
for _, sname := range services {
|
||||||
if err := cfg.services.Init(sname); err != nil {
|
if err := cfg.services.Init(sname); err != nil {
|
||||||
check(fmt.Errorf("couldn't connect to %s: %w", sname, err))
|
check(fmt.Errorf("couldn't connect to %s: %w", sname, err))
|
||||||
|
@ -53,6 +53,10 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !cfg.performBackfeed {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "Found %d existing syndications to backfeed from %s\n", len(toBackfeed), feed)
|
fmt.Fprintf(os.Stderr, "Found %d existing syndications to backfeed from %s\n", len(toBackfeed), feed)
|
||||||
if err := bkfd.BackfeedAll(toBackfeed); err != nil {
|
if err := bkfd.BackfeedAll(toBackfeed); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Couldn't backfeed syndications: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Couldn't backfeed syndications: %v\n", err)
|
||||||
|
|
|
@ -1,7 +1,23 @@
|
||||||
package instagram
|
package instagram
|
||||||
|
|
||||||
import "github.com/by-jp/www.byjp.me/tools/syndicate/shared"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/by-jp/www.byjp.me/tools/syndicate/shared"
|
||||||
|
)
|
||||||
|
|
||||||
func (s *service) Interactions(url string) ([]shared.Interaction, error) {
|
func (s *service) Interactions(url string) ([]shared.Interaction, error) {
|
||||||
return nil, nil
|
u, err := s.insta.Profiles.ByName(s.username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to load your feed to scan for interactions: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
feed := u.Feed()
|
||||||
|
fmt.Println(feed, feed.Items, feed.NumResults, feed.Status)
|
||||||
|
|
||||||
|
if err := feed.GetCommentInfo(); err != nil {
|
||||||
|
return nil, fmt.Errorf("unable load feed comment info: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,12 @@ func (s *service) Interactions(url string) ([]shared.Interaction, error) {
|
||||||
for _, acc := range favs {
|
for _, acc := range favs {
|
||||||
ias = append(ias, shared.Interaction{
|
ias = append(ias, shared.Interaction{
|
||||||
Emoji: "⭐️",
|
Emoji: "⭐️",
|
||||||
|
URL: url,
|
||||||
Author: shared.Author{
|
Author: shared.Author{
|
||||||
Name: acc.DisplayName,
|
Name: acc.DisplayName,
|
||||||
URL: acc.URL,
|
URL: acc.URL,
|
||||||
AvatarURL: acc.Avatar,
|
AvatarURL: acc.Avatar,
|
||||||
},
|
},
|
||||||
Timestamp: acc.CreatedAt,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,12 +42,12 @@ func (s *service) Interactions(url string) ([]shared.Interaction, error) {
|
||||||
for _, acc := range reblogs {
|
for _, acc := range reblogs {
|
||||||
ias = append(ias, shared.Interaction{
|
ias = append(ias, shared.Interaction{
|
||||||
Emoji: "🔁",
|
Emoji: "🔁",
|
||||||
|
URL: url,
|
||||||
Author: shared.Author{
|
Author: shared.Author{
|
||||||
Name: acc.DisplayName,
|
Name: acc.DisplayName,
|
||||||
URL: acc.URL,
|
URL: acc.URL,
|
||||||
AvatarURL: acc.Avatar,
|
AvatarURL: acc.Avatar,
|
||||||
},
|
},
|
||||||
Timestamp: acc.CreatedAt,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,12 @@ type Interaction struct {
|
||||||
// eg. Repost is 🔁, Facebook is 👍, Instagram is ♥️, Mastodon is ⭐️, Medium is 👏
|
// eg. Repost is 🔁, Facebook is 👍, Instagram is ♥️, Mastodon is ⭐️, Medium is 👏
|
||||||
Emoji string `json:"emoji,omitempty"`
|
Emoji string `json:"emoji,omitempty"`
|
||||||
// The URL of the original interaction
|
// The URL of the original interaction
|
||||||
URL string `json:"url,omitempty"`
|
URL string `json:"url"`
|
||||||
// If there's a comment associated with the interaction
|
// If there's a comment associated with the interaction
|
||||||
Comment string `json:"comment,omitempty"`
|
Comment string `json:"comment,omitempty"`
|
||||||
// Details of the author
|
// Details of the author
|
||||||
Author Author `json:"author"`
|
Author Author `json:"author"`
|
||||||
Timestamp time.Time `json:"timestamp"`
|
Timestamp time.Time `json:"timestamp,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Author struct {
|
type Author struct {
|
||||||
|
|
Loading…
Reference in a new issue