tangled
alpha
login
or
join now
quilling.dev
/
social-app
7
fork
atom
An ATproto social media client -- with an independent Appview.
7
fork
atom
overview
issues
pulls
pipelines
chore: merge from upstream at 2025-09-18-011544
github-actions[bot]
5 months ago
eb338d6a
61535897
+51
-10
3 changed files
expand all
collapse all
unified
split
bskyweb
cmd
bskyweb
server.go
templates
base.html
post.html
+10
-4
bskyweb/cmd/bskyweb/server.go
···
488
}
489
}
490
0
491
if !unauthedViewingOkay {
0
0
0
0
0
0
0
492
return c.Render(http.StatusOK, "post.html", data)
493
}
494
-
did := pv.Did
495
-
data["did"] = did
496
497
// then fetch the post thread (with extra context)
498
-
uri := fmt.Sprintf("at://%s/app.bsky.feed.post/%s", did, rkey)
499
tpv, err := appbsky.FeedGetPostThread(ctx, srv.xrpcc, 1, 0, uri)
500
if err != nil {
501
log.Warnf("failed to fetch post: %s\t%v", uri, err)
502
return c.Render(http.StatusOK, "post.html", data)
503
}
504
-
req := c.Request()
505
postView := tpv.Thread.FeedDefs_ThreadViewPost.Post
506
data["postView"] = postView
507
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
···
488
}
489
}
490
491
+
req := c.Request()
492
if !unauthedViewingOkay {
493
+
// Provide minimal OpenGraph data for auth-required posts
494
+
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
495
+
data["requiresAuth"] = true
496
+
data["profileHandle"] = pv.Handle
497
+
if pv.DisplayName != nil {
498
+
data["profileDisplayName"] = *pv.DisplayName
499
+
}
500
return c.Render(http.StatusOK, "post.html", data)
501
}
0
0
502
503
// then fetch the post thread (with extra context)
504
+
uri := fmt.Sprintf("at://%s/app.bsky.feed.post/%s", pv.Did, rkey)
505
tpv, err := appbsky.FeedGetPostThread(ctx, srv.xrpcc, 1, 0, uri)
506
if err != nil {
507
log.Warnf("failed to fetch post: %s\t%v", uri, err)
508
return c.Render(http.StatusOK, "post.html", data)
509
}
510
+
511
postView := tpv.Thread.FeedDefs_ThreadViewPost.Post
512
data["postView"] = postView
513
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
+1
-1
bskyweb/templates/base.html
···
94
<meta name="theme-color">
95
<meta name="application-name" content="Bluesky">
96
<meta name="generator" content="bskyweb">
97
-
<meta property="og:site_name" content="Bluesky Social" />
98
<meta name="twitter:site" content="@bluesky" />
99
<link type="application/activity+json" href="" />
100
···
94
<meta name="theme-color">
95
<meta name="application-name" content="Bluesky">
96
<meta name="generator" content="bskyweb">
97
+
<meta property="og:site_name" content="Bluesky Social">
98
<meta name="twitter:site" content="@bluesky" />
99
<link type="application/activity+json" href="" />
100
+40
-5
bskyweb/templates/post.html
···
3
{% block head_title %}
4
{%- if postView -%}
5
@{{ postView.Author.Handle }} on Bluesky
0
0
6
{%- else -%}
7
Bluesky
8
{%- endif -%}
···
11
{% block html_head_extra -%}
12
{%- if postView -%}
13
<meta property="og:type" content="article">
14
-
<meta property="profile:username" content="{{ profileView.Handle }}">
15
{%- if requestURI %}
16
<meta property="og:url" content="{{ requestURI }}">
17
<link rel="canonical" href="{{ requestURI|canonicalize_url }}" />
···
32
<meta property="twitter:image" content="{{ imgThumbUrl }}">
33
{% endfor %}
34
<meta name="twitter:card" content="summary_large_image">
35
-
{%- elif postView.Author.Avatar %}
36
-
<meta name="twitter:card" content="summary">
37
<meta property="og:image" content="{{ postView.Author.Avatar }}">
38
<meta property="twitter:image" content="{{ postView.Author.Avatar }}">
0
39
{% endif %}
40
<meta name="twitter:label1" content="Posted At">
41
<meta name="twitter:value1" content="{{ postView.IndexedAt }}">
42
-
<meta name="article:published_time" content="{{ postView.IndexedAt }}">
43
-
<meta name="article:published_time" content="{{ postView.IndexedAt }}">
0
0
0
0
0
0
0
0
0
0
0
44
<link rel="alternate" type="application/json+oembed" href="https://embed.bsky.app/oembed?format=json&url={{ postView.Uri | urlencode }}" />
45
<link rel="alternate" href="{{ postView.Uri }}" />
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
46
{% endif -%}
47
{%- endblock %}
48
···
55
<p id="bsky_did">{{ postView.Author.Did }}</p>
56
<p id="bsky_post_text">{{ postText }}</p>
57
<p id="bsky_post_indexedat">{{ postView.IndexedAt }}</p>
0
0
0
0
0
0
58
</div>
59
{% endif -%}
60
{%- endblock %}
···
3
{% block head_title %}
4
{%- if postView -%}
5
@{{ postView.Author.Handle }} on Bluesky
6
+
{%- elif requiresAuth and profileHandle -%}
7
+
@{{ profileHandle }} on Bluesky
8
{%- else -%}
9
Bluesky
10
{%- endif -%}
···
13
{% block html_head_extra -%}
14
{%- if postView -%}
15
<meta property="og:type" content="article">
16
+
<meta property="profile:username" content="{{ postView.Author.Handle }}">
17
{%- if requestURI %}
18
<meta property="og:url" content="{{ requestURI }}">
19
<link rel="canonical" href="{{ requestURI|canonicalize_url }}" />
···
34
<meta property="twitter:image" content="{{ imgThumbUrl }}">
35
{% endfor %}
36
<meta name="twitter:card" content="summary_large_image">
37
+
{% else %}
0
38
<meta property="og:image" content="{{ postView.Author.Avatar }}">
39
<meta property="twitter:image" content="{{ postView.Author.Avatar }}">
40
+
<meta name="twitter:card" content="summary">
41
{% endif %}
42
<meta name="twitter:label1" content="Posted At">
43
<meta name="twitter:value1" content="{{ postView.IndexedAt }}">
44
+
{%- if postView.LikeCount %}
45
+
<meta name="twitter:label2" content="Likes">
46
+
<meta name="twitter:value2" content="{{ postView.LikeCount }}">
47
+
{% endif -%}
48
+
{%- if postView.ReplyCount %}
49
+
<meta name="twitter:label3" content="Replies">
50
+
<meta name="twitter:value3" content="{{ postView.ReplyCount }}">
51
+
{% endif -%}
52
+
{%- if postView.RepostCount %}
53
+
<meta name="twitter:label4" content="Reposts">
54
+
<meta name="twitter:value4" content="{{ postView.RepostCount }}">
55
+
{% endif -%}
56
+
<meta property="article:published_time" content="{{ postView.IndexedAt }}">
57
<link rel="alternate" type="application/json+oembed" href="https://embed.bsky.app/oembed?format=json&url={{ postView.Uri | urlencode }}" />
58
<link rel="alternate" href="{{ postView.Uri }}" />
59
+
{%- elif requiresAuth and profileHandle -%}
60
+
<meta property="og:type" content="article">
61
+
<meta property="profile:username" content="{{ profileHandle }}">
62
+
{%- if requestURI %}
63
+
<meta property="og:url" content="{{ requestURI }}">
64
+
<link rel="canonical" href="{{ requestURI|canonicalize_url }}" />
65
+
{% endif -%}
66
+
{%- if profileDisplayName %}
67
+
<meta property="og:title" content="{{ profileDisplayName }} (@{{ profileHandle }})">
68
+
{% else %}
69
+
<meta property="og:title" content="@{{ profileHandle }}">
70
+
{% endif -%}
71
+
<meta name="description" content="This post requires authentication to view.">
72
+
<meta property="og:description" content="This post requires authentication to view.">
73
+
<meta property="twitter:description" content="This post requires authentication to view.">
74
+
<meta name="twitter:card" content="summary">
75
{% endif -%}
76
{%- endblock %}
77
···
84
<p id="bsky_did">{{ postView.Author.Did }}</p>
85
<p id="bsky_post_text">{{ postText }}</p>
86
<p id="bsky_post_indexedat">{{ postView.IndexedAt }}</p>
87
+
</div>
88
+
{%- elif requiresAuth and profileHandle -%}
89
+
<div id="bsky_post_summary">
90
+
<h3>Post</h3>
91
+
<p id="bsky_handle">{{ profileHandle }}</p>
92
+
<p id="bsky_post_text">This post requires authentication to view.</p>
93
</div>
94
{% endif -%}
95
{%- endblock %}