代码拉取完成,页面将自动刷新
<!-- 与 Mastodon3 增加 ArtalkGo 评论 -->
<style>
.header {
background-image: url('https://cdn.ftls.xyz/images/2023/06/20230820123739.png');
background-size: cover;
background-position: center;
height: 200px;
position: relative;
margin-bottom: 70px;
border-radius: 5px;
box-shadow: 0 0 10px 1px #2d96bd;
}
.avatar {
width: 100px;
height: 120px;
border-radius: 15%;
box-shadow: 0 0 3px 0.5px rgb(146, 255, 146);
}
.toots-container {
margin: 0 auto;
}
.toot {
margin-bottom: 10px;
}
.toot .avatar {
width: 50px;
height: 50px;
border-radius: 50%;
margin-right: 5px;
}
.toot-info {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.basic-info {
position: absolute;
/* Use absolute positioning */
bottom: -70px;
display: flex;
align-items: center;
margin-left: 10px;
}
.toot-stats {
display: flex;
justify-content: flex-end;
/* 将元素靠右对齐 */
}
.toot-stats i {
margin-right: 3rem;
}
.basic-field-status {
border: 1px solid #2d97bd86;
border-radius: 30px;
background-color: rgba(255, 255, 255, 0.05);
}
.basic-text {
margin-top: 50px;
}
/* Cat Ear */
.basic-avatar img {
position: absolute;
z-index: 2;
object-fit: cover;
width: 100px;
height: 100px;
left: calc(50% - 50px);
}
.basic-avatar::before,
.basic-avatar::after {
background: #ebbcba;
border: solid 3px #ead9d8;
box-sizing: border-box;
content: "";
display: inline-block;
height: 50px;
width: 50px;
margin-top: -5px;
/* margin-right: -5px; */
}
.basic-avatar::before {
border-radius: 25% 75% 75%;
transform: rotate(37.5deg) skew(30deg);
}
.basic-avatar::after {
border-radius: 75% 25% 75% 75%;
transform: rotate(-37.5deg) skew(-30deg);
}
.basic-avatar img {
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: 0;
z-index: 1;
overflow: hidden;
object-fit: cover;
}
.basic-avatar img:hover {
position: absolute;
}
.basic-avatar {
height: 120px;
}
.basic-avatar:hover::before {
animation: earwiggleleft 1s infinite;
}
.basic-avatar:hover::after {
animation: earwiggleright 1s infinite;
}
/* Cat Ear End */
/* Media Query for Mobile Devices */
@media only screen and (max-width: 600px) {
.header {
height: 150px;
padding: 10px;
}
.toots-container {
padding: 10px;
}
.toot .avatar {
width: 40px;
height: 40px;
}
.avatar {
width: 100px;
height: 100px;
}
.basic-info {
margin-left: 2px;
}
.basic-avatar::before,
.basic-avatar::after {
margin-top: -3px;
}
}
/* 430px or 200px hide img and ears */
@media only screen and (max-width: 430px) {
.basic-avatar::before,
.basic-avatar::after {
display: none;
}
.basic-text {
margin-top: 100px;
margin-left: -25px;
}
.basic-avatar img {
margin-right: 10px;
display: none;
}
}
.mdi--reply {
display: inline-block;
width: 1.3em;
height: 1.3em;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M10 9V5l-7 7l7 7v-4.1c5 0 8.5 1.6 11 5.1c-1-5-4-10-11-11'/%3E%3C/svg%3E");
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
.mdi--star {
display: inline-block;
width: 1.3em;
height: 1.3em;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.62L12 2L9.19 8.62L2 9.24l5.45 4.73L5.82 21z'/%3E%3C/svg%3E");
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
.mdi--twitter-retweet {
display: inline-block;
width: 1.3em;
height: 1.3em;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M6 5.75L10.25 10H7v6h6.5l2 2H7a2 2 0 0 1-2-2v-6H1.75zm12 12.5L13.75 14H17V8h-6.5l-2-2H17a2 2 0 0 1 2 2v6h3.25z'/%3E%3C/svg%3E");
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
</style>
<body>
<div class="header">
<div class="basic-info">
<div class="basic-avatar">
<a href="/kkbt/" title="恐咖兵糖"><img src="https://ftls.xyz/img/avatar.webp" alt="kkbt" class="avatar"></a>
</div>
<div class="basic-text">
<strong> 恐咖兵糖</strong> <a href="https://fmb.ftls.xyz/@kkbt">@kkbt</a>
<span id="basic-field-status" class="basic-field-status"></span>
<br> <a href="/whispers/">微语</a> <span id="basic-statuses-count"></span> 条
<a href="https://gotosocial-kkbt-tools-xkzlczgovq.cn-hangzhou.fcapp.run/@kkbt/feed.rss">RSS</a>
</div>
</div>
</div>
<div id="basic-bio"></div>
<div id="basic-profile"></div>
<hr style="margin: 0.5rem 0;">
<div id="toots-content" class="toots-container">
<div class="toot" id="toots">
<!-- show toots -->
</div>
<i id="toots-loading" class="fa fa-spinner fa-pulse fa-3x fa-fw" style="display: none;place-items: center;">
<svg xmlns="http://www.w3.org/2000/svg" width="5em" height="5em" viewBox="0 0 256 256">
<path fill="currentColor"
d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24m39.11 25.19C170.24 83.71 155 99.44 135 113.61c-2.25-24.48-8.44-49.8-38.37-67.82a87.89 87.89 0 0 1 70.5 3.4ZM40.18 133.54c28.34-20 49.57-14.68 71.87-4.39c-20.05 14.19-38.86 32.21-39.53 67.11a87.92 87.92 0 0 1-32.34-62.72m136.5 67.73c-31.45-14.55-37.47-35.58-39.71-60c12.72 5.86 26.31 10.75 41.3 10.75c11.33 0 23.46-2.8 36.63-10.08a88.2 88.2 0 0 1-38.22 59.33" />
</svg>
</i>
<button id="toots-moreButton" onclick="tootsShowMore()"><a>更多</a></button>
</div>
</body>
<link href="/lib/artalk/Artalk.min.css" rel="stylesheet">
<script src="/lib/artalk/Artalk.js"></script>
<!-- <link href="/lib/artalk/Artalk.min.css" rel="stylesheet">
<script src="/lib/artalk/Artalk.js"></script> -->
<script type="text/javascript" src="/js/time-fmt.min.js"></script>
<!-- view-image.js 轻量画廊 -->
<!-- <script type="text/javascript" src="https://cdn.ftls.xyz/static/whispers/assets/js/view-image.min.js"></script> -->
<!-- medium-zoom.js 用于图片放缩预览 -->
<script type="text/javascript" src="//cdn.ftls.xyz/js/utils/medium-zoom.min.js"></script>
<script>
let maxId = null; // 初始值为 null,表示第一页
let isFirst = true; // 首次加载
const tootsDiv = document.getElementById('toots');
const tootsMoreButton = document.getElementById('toots-moreButton');
const tootsLoading = document.getElementById('toots-loading');
const urlObject = new URL(window.location.href);
const idValue = urlObject.searchParams.get("id");
let mediumZoomK = 0;
// 获取 Mastodon 用户公开Toots 限制条数 默认5 排除回复 toot
async function getPublicToots() {
let limit = "{{ .Get 2 | default 5 }}";
if (idValue != null && isFirst) {
isFirst = false;
const response = await fetch("{{ .Get 0 }}/api/v1/statuses/" + idValue, {
headers: {
'Authorization': "Bearer {{ .Site.Params.bot_token }}"
}
})
const toot = await response.json();
return [toot];
}
const queryParams = maxId ? (`?limit=${limit}&max_id=${maxId}`) : "?limit=" + limit;
const response = await fetch("{{ .Get 0 }}/api/v1/accounts/{{ .Get 1 }}/statuses" + queryParams + "&exclude_replies=true");
const toots = await response.json();
return toots;
}
// 解析ULID
function parseULID(ulid) {
const base32Chars = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
const timestamp = parseInt(ulid.slice(0, 10).split('').map(char => base32Chars.indexOf(char)).map(index => index.toString(2).padStart(5, '0')).join(''), 2);
const randomPart = ulid.slice(10);
return {
timestamp: new Date(timestamp),
randomPart: randomPart
};
}
let artalk;
function initArtalk(father, toot) {
// return;
const commentsArtalk = document.createElement("div");
commentsArtalk.id = `comments-${toot.id}-artalk`;
father.appendChild(commentsArtalk);
const config = {
el: `#comments-${toot.id}-artalk`, // 绑定元素的 Selector
pageKey: `?id=${toot.id}`, // 固定链接 (留空自动获取)
pageTitle: toot.text.slice(0, 20) + '...', // 页面标题 (留空自动获取)
server: "https://func-aceh-kkbt-tools-irakvvlhcy.cn-hangzhou.fcapp.run", // 后端地址
// server: "http://127.0.0.1:23366", // 后端地址
site: '微语', // 你的站点名
};
console.log(config);
// 释放上一个 artalk 实例
if (artalk != undefined) {
artalk.destroy();
}
artalk = Artalk.init(config)
artalk.setDarkMode(window.isDark)
}
// 将Toots显示在页面上
async function displayToots() {
try {
tootsLoading.style.display = "grid";
tootsMoreButton.style.display = 'none';
const toots = await getPublicToots();
if (toots && toots.length > 0) {
displayBioProfile(toots[0]);
toots.forEach(toot => {
// console.log(parseULID(toot.id)); // 解析 ULID
const tootDiv = document.createElement("div");
tootDiv.classList.add("toot");
// 评论按钮
const button = document.createElement("button");
// button.innerHTML = "<i class=\"far fa-comments fa-fw\"></i>"
button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 48 48"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M44 6H4v30h9v5l10-5h21zM14 19.5v3m10-3v3m10-3v3"/></svg>'
button.id = toot.id;
button.type = 'button';
button.title = "评论"
button.style = "float: right;"
tootDiv.appendChild(button);
const tootInfoDiv = document.createElement("div");
tootInfoDiv.classList.add("toot-info");
const tootAvatar = document.createElement("div");
tootAvatar.classList.add("toot-avatar");
const profileImage = document.createElement("img");
profileImage.src = "https://ftls.xyz/img/avatar.webp";
profileImage.classList.add("avatar");
profileImage.alt = toot.account.display_name;
const tootProfileDiv = document.createElement("div");
tootProfileDiv.innerHTML = `<strong>${toot.account.display_name}</strong> <a href="${toot.url}" target="_blank">@${toot.account.acct}</a><br><small>${formatTime(toot.created_at)}</small>`;
tootAvatar.appendChild(profileImage);
tootInfoDiv.appendChild(profileImage);
tootInfoDiv.appendChild(tootProfileDiv);
const contentDiv = document.createElement("div");
contentDiv.classList.add("toot-content");
contentDiv.innerHTML = toot.content.replace(/<img/g, `<img loading="lazy" class="toot-img" data-zoomable-${mediumZoomK}`);
// contentDiv.innerHTML = toot.content;
// media loading="lazy"
for (let i = 0; i < toot.media_attachments.length; i++) {
const media = toot.media_attachments[i];
contentDiv.innerHTML += `<img loading="lazy" src="${media.url}">`;
}
const tootStats = document.createElement("a");
tootStats.href = toot.url;
tootStats.target = "_blank";
tootStats.className = "toot-stats";
if (toot.replies_count + toot.favourites_count + toot.reblogs_count != 0) {
tootStats.innerHTML += `<span class="mdi--reply"></span> ${toot.replies_count} `;
tootStats.innerHTML += `<span class="mdi--star"></span> ${toot.favourites_count} `;
tootStats.innerHTML += `<span class="mdi--twitter-retweet"></span> ${toot.reblogs_count}`;
}
const hr = document.createElement("hr");
hr.style = "margin: 0.5rem 0;"
// 评论锚点
const commentAnchor = document.createElement("div");
button.onclick = function () {
initArtalk(commentAnchor, toot);
}
tootDiv.appendChild(tootInfoDiv);
tootDiv.appendChild(contentDiv);
tootDiv.appendChild(tootStats);
tootDiv.appendChild(commentAnchor);
tootDiv.appendChild(hr);
tootsDiv.appendChild(tootDiv);
maxId = toot.id; // 更新最大 ID
// 如果 只有一个 自动打开评论区
if (toots.length == 1) {
initArtalk(commentAnchor, toot);
}
});
// 初始化 medium-zoom
mediumZoom(`[data-zoomable-${mediumZoomK}]`, {
background: 'rgba(0, 0, 0, 0.8)'
});
mediumZoomK++;
tootsMoreButton.style.display = 'block';
} else {
tootsMoreButton.style.display = 'none';
}
} catch (error) {
console.error('获取 Toots 时出错:', error);
tootsDiv.innerHTML += error.message;
}
tootsLoading.style.display = "none";
}
function tootsShowMore() {
displayToots();
}
function displayBioProfile(statuse) {
document.getElementById("basic-statuses-count").innerText = `${statuse.account.statuses_count}`;
document.getElementById("basic-bio").innerHTML = statuse.account.note;
let fieldsHtml = "";
statuse.account.fields.forEach(field => {
fieldsHtml += `<strong>${field.name}</strong> <span>${field.value}</span><br>`;
if (field.name === "Status") {
document.getElementById("basic-field-status").innerHTML = ` ${field.value} `;
}
});
document.getElementById("basic-profile").innerHTML = fieldsHtml;
}
displayToots();
// 页面加载时调用显示Toots函数
// window.onload = displayToots;
// window.ViewImage && ViewImage.init('.toot-img');
</script>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。