mirror of
https://github.com/by-jp/www.byjp.me.git
synced 2025-08-09 05:36:07 +01:00
Add comments
This commit is contained in:
parent
50278343bc
commit
0953eb99a2
14 changed files with 193 additions and 19 deletions
|
@ -454,4 +454,62 @@ figure {
|
|||
height: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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 }}
|
||||
</date>
|
||||
</p>
|
||||
|
||||
{{ partial "interactions.html" . }}
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
|
|
@ -53,17 +53,31 @@ func (b *backfeeder) BackfeedAll(toBackfeed ToBackfeedList) 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
|
||||
}
|
||||
path := filepath.Join(dir, "interactions.json")
|
||||
path := dir + ".json"
|
||||
|
||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
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
|
||||
urlToPublicPath func(string) string
|
||||
urlToInteractionsPath func(string) string
|
||||
|
||||
performBackfeed bool
|
||||
}
|
||||
|
||||
func parseConfig(cfgPath string) (*config, error) {
|
||||
|
@ -50,12 +52,16 @@ func parseConfig(cfgPath string) (*config, error) {
|
|||
feeds: []string{},
|
||||
services: services.New(),
|
||||
syndicationMatchers: make(map[string]*regexp.Regexp),
|
||||
performBackfeed: cfgData.InteractionsDir != "",
|
||||
urlToPublicPath: func(url string) string {
|
||||
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))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
cfg.content, err = doublestar.Glob(os.DirFS("."), cfgData.ContentGlob)
|
||||
|
@ -80,11 +86,14 @@ func parseConfig(cfgPath string) (*config, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
bf, err := svc.BackfeedMatcher()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot perform backfeed matching for '%s' because %w", name, err)
|
||||
if cfg.performBackfeed {
|
||||
bf, err := svc.BackfeedMatcher()
|
||||
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)
|
||||
}
|
||||
cfg.tagMatcher, err = shared.TagMatcher(serviceTags)
|
||||
|
|
|
@ -34,7 +34,7 @@ func main() {
|
|||
check(err)
|
||||
|
||||
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 {
|
||||
if err := cfg.services.Init(sname); err != nil {
|
||||
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)
|
||||
if err := bkfd.BackfeedAll(toBackfeed); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Couldn't backfeed syndications: %v\n", err)
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
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) {
|
||||
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 {
|
||||
ias = append(ias, shared.Interaction{
|
||||
Emoji: "⭐️",
|
||||
URL: url,
|
||||
Author: shared.Author{
|
||||
Name: acc.DisplayName,
|
||||
URL: acc.URL,
|
||||
AvatarURL: acc.Avatar,
|
||||
},
|
||||
Timestamp: acc.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -42,12 +42,12 @@ func (s *service) Interactions(url string) ([]shared.Interaction, error) {
|
|||
for _, acc := range reblogs {
|
||||
ias = append(ias, shared.Interaction{
|
||||
Emoji: "🔁",
|
||||
URL: url,
|
||||
Author: shared.Author{
|
||||
Name: acc.DisplayName,
|
||||
URL: acc.URL,
|
||||
AvatarURL: acc.Avatar,
|
||||
},
|
||||
Timestamp: acc.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -28,12 +28,12 @@ type Interaction struct {
|
|||
// eg. Repost is 🔁, Facebook is 👍, Instagram is ♥️, Mastodon is ⭐️, Medium is 👏
|
||||
Emoji string `json:"emoji,omitempty"`
|
||||
// The URL of the original interaction
|
||||
URL string `json:"url,omitempty"`
|
||||
URL string `json:"url"`
|
||||
// If there's a comment associated with the interaction
|
||||
Comment string `json:"comment,omitempty"`
|
||||
// Details of the author
|
||||
Author Author `json:"author"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Timestamp time.Time `json:"timestamp,omitempty"`
|
||||
}
|
||||
|
||||
type Author struct {
|
||||
|
|
Loading…
Reference in a new issue