Repository navigation
Expand file tree
/
Copy pathscript.js
More file actions
132 lines (99 loc) · 3.35 KB
/
Copy pathscript.js
File metadata and controls
132 lines (99 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
console.log("PerfectSky Post script loaded.");
const statusEl = document.getElementById("status");
const resultadoEl = document.getElementById("resultado");
// Trending feed (MIT published)
const API_URL =
"https://public.api.bsky.app/xrpc/app.bsky.feed.getFeed?feed=" +
encodeURIComponent("at://did:plc:jlyxq2frdkpnkwhzldvmjlrv/app.bsky.feed.generator/aaadxgnfze66k");
init();
async function init() {
try {
statusEl.textContent = "Loading Bluesky feed...";
const response = await fetch(API_URL);
if (!response.ok) {
throw new Error("HTTP Error " + response.status);
}
const data = await response.json();
if (!data.feed || data.feed.length === 0) {
throw new Error("Feed returned empty");
}
const posts = data.feed;
const stats = analyze(posts);
resultadoEl.textContent = generateText(stats);
statusEl.textContent = "Analysis completed successfully";
} catch (error) {
console.error(error);
statusEl.textContent = "Error loading feed";
resultadoEl.textContent =
"Could not analyze feed.\n\n" + error.message;
}
}
function analyze(posts) {
let totalChars = 0;
let totalWords = 0;
let totalHashtags = 0;
let withImage = 0;
let withVideo = 0;
let noMedia = 0;
let withLinks = 0;
let replies = 0;
let originals = 0;
let quotes = 0;
for (const item of posts) {
const post = item.post;
const text = post.record.text || "";
totalChars += text.length;
const words = text.trim().split(/\s+/).filter(Boolean);
totalWords += words.length;
const hashtags = text.match(/#\w+/g) || [];
totalHashtags += hashtags.length;
const embedType = post.embed?.$type || "";
if (embedType.includes("images")) withImage++;
else if (embedType.includes("video")) withVideo++;
else noMedia++;
const hasLink =
text.includes("http://") ||
text.includes("https://") ||
embedType.includes("external");
if (hasLink) withLinks++;
if (item.reply) replies++;
else if (embedType.includes("record")) quotes++;
else originals++;
}
const total = posts.length;
return {
total,
avgChars: Math.round(totalChars / total),
avgWords: Math.round(totalWords / total),
avgHashtags: (totalHashtags / total).toFixed(1),
imagePct: percentage(withImage, total),
videoPct: percentage(withVideo, total),
noMediaPct: percentage(noMedia, total),
linksPct: percentage(withLinks, total),
repliesPct: percentage(replies, total),
originalsPct: percentage(originals, total),
quotesPct: percentage(quotes, total),
};
}
function percentage(value, total) {
return Math.round((value / total) * 100);
}
function generateText(stats) {
return `
-----------------------------------------
| Style Analysis (last 24h) |
-----------------------------------------
Results:
• Posts analyzed: ${stats.total}
• Avg characters: ${stats.avgChars}
• Avg words: ${stats.avgWords}
• Avg hashtags: ${stats.avgHashtags}
• % with image: ${stats.imagePct}%
• % with video: ${stats.videoPct}%
• % without media: ${stats.noMediaPct}%
• % with links: ${stats.linksPct}%
• % replies: ${stats.repliesPct}%
• % originals: ${stats.originalsPct}%
• % quotes: ${stats.quotesPct}%
`;
}