forked from 3r1s-s/meo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshare.html
389 lines (326 loc) · 18.6 KB
/
share.html
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
<!DOCTYPE html>
<html lang="en">
<head>
<title>meo</title>
<link rel="icon" href="images/meo96.png">
<link rel="apple-touch-icon" sizes="180x180" href="images/meo.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="theme-color" content="#307ce7">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="stylesheet" href="fonts.css">
<link rel="stylesheet" href="share.css">
<link rel="stylesheet" href="themes.css">
</head>
<body>
<div class="shell">
<div class="main" id="msgs">
</div>
<div class="footer">
<a href="https://meo-32r.pages.dev">
<svg width="80" height="44.25" viewBox="0 0 321 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M124.695 17.2859L175.713 0.216682C184.63 -1.38586 192.437 6.14467 190.775 14.7463L177.15 68.2185C184.648 86.0893 187.163 104.122 187.163 115.032C187.163 143.057 174.929 178 95.4997 178C16.0716 178 3.83691 143.057 3.83691 115.032C3.83691 104.122 6.35199 86.0893 13.8498 68.2185L0.224791 14.7463C-1.43728 6.14467 6.3705 -1.38586 15.2876 0.216682L66.3051 17.2859C74.8856 14.6362 84.5688 13.2176 95.4997 13.429C106.431 13.2176 116.114 14.6362 124.695 17.2859ZM174.699 124.569H153.569V80.6255C153.569 75.6157 151.762 72.1804 146.896 72.1804C143.143 72.1804 139.529 74.6137 135.775 78.3353V124.569H114.785V80.6255C114.785 75.6157 112.977 72.1804 108.112 72.1804C104.22 72.1804 100.744 74.6137 96.9909 78.3353V124.569H76V54.4314H94.4887L96.0178 64.0216C102.134 57.5804 108.39 53 117.148 53C126.462 53 131.605 57.7235 134.107 64.0216C140.224 57.7235 146.896 53 155.376 53C168.026 53 174.699 61.1588 174.699 74.7569V124.569ZM247.618 89.3569C247.618 91.5039 247.479 93.7941 247.201 94.9392H206.331C207.443 105.961 213.838 110.255 223.012 110.255C230.519 110.255 237.887 107.392 245.393 102.955L247.479 118.127C240.111 122.994 231.075 126 220.371 126C199.936 126 185.34 114.835 185.34 89.7863C185.34 66.8843 198.963 53 217.452 53C238.304 53 247.618 69.0314 247.618 89.3569ZM227.6 83.0588C226.905 72.4667 223.29 67.0274 216.896 67.0274C211.057 67.0274 206.887 72.3235 206.192 83.0588H227.6ZM288.054 126C306.96 126 321 111.973 321 89.5C321 67.0274 307.099 53 288.193 53C269.426 53 255.525 67.1706 255.525 89.6431C255.525 112.116 269.287 126 288.054 126ZM288.193 70.749C296.256 70.749 300.704 78.3353 300.704 89.6431C300.704 100.951 296.256 108.537 288.193 108.537C280.269 108.537 275.821 100.808 275.821 89.5C275.821 78.049 280.13 70.749 288.193 70.749Z" fill="#FEFEFE"/>
</svg>
</a>
</div>
</div>
<script>
let pfpCache = "";
async function loadsharedpost() {
const urlParams = new URLSearchParams(window.location.search);
const id = urlParams.get('id');
if (!id) {
return;
}
const api = `https://api.meower.org/posts?id=${id}`;
console.log(api);
try {
const response = await fetch(api);
const data = await response.json();
loadpost(data);
} catch (error) {
console.error('Fetch Error:', error);
}
}
function loadpost(p) {
if (p.u == "Discord" || p.u == "SplashBridge") {
var rcon = p.p;
var parts = rcon.split(': ');
var user = parts[0];
var content = parts.slice(1).join(': ');
} else {
var content = p.p;
var user = p.u;
}
var postContainer = document.createElement("div");
postContainer.id = p._id;
postContainer.classList.add("post");
var wrapperDiv = document.createElement("div");
wrapperDiv.classList.add("wrapper");
var pfpDiv = document.createElement("div");
pfpDiv.classList.add("pfp");
var pstdte = document.createElement("i");
pstdte.classList.add("date");
tsr = p.t.e;
tsra = tsr * 1000;
tsrb = Math.trunc(tsra);
var ts = new Date();
ts.setTime(tsrb);
sts = ts.toLocaleString();
pstdte.innerText = sts;
var pstinf = document.createElement("h3");
pstinf.innerHTML = "<span id='username'>" + user + "</span>";
if (p.u == "Discord" || p.u == "SplashBridge") {
var bridged = document.createElement("bridge");
bridged.innerText = "Bridged";
bridged.setAttribute("title", "This post has been bridged from another platform.");
pstinf.appendChild(bridged);
}
pstinf.appendChild(pstdte);
wrapperDiv.appendChild(pstinf);
var replyregex = /@(\w+)\s+"([^"]*)"\s+\(([^)]+)\)/g;
var match = replyregex.exec(content);
if (match) {
var replyid = match[3];
var pageContainer = document.getElementById("msgs");
if (pageContainer.firstChild) {
pageContainer.insertBefore(postContainer, pageContainer.firstChild);
} else {
pageContainer.appendChild(postContainer);
}
loadreply(replyid).then(replycontainer => {
var pElement = wrapperDiv.getElementsByTagName("p")[0];
wrapperDiv.insertBefore(replycontainer, pElement);
});
content = content.replace(match[0], '').trim();
}
var postContentText = document.createElement("p");
blist = ["", " ", "# ", "## ", "### ", "#### ", "##### ", "###### ", "\n"];
if (!blist.includes(content)) {
var asplc = content;
var escapedinput = asplc
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
var textContent = escapedinput
.replace(/\*\*\*\*(.*?[^\*])\*\*\*\*/g, '$1')
.replace(/\*\*(.*?[^\*])\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?[^\*])\*/g, '<em>$1</em>')
.replace(/```([\s\S]*?)```/g, '<div class="code"><code>$1</code></div>')
.replace(/``([^`]+)``/g, '<code>$1</code>')
.replace(/`([^`]+)`/g, '<code>$1</code>')
.replace(/^# (.*?$)/gm, '<h1>$1</h1>')
.replace(/^## (.*?$)/gm, '<h2>$1</h2>')
.replace(/^### (.*?$)/gm, '<h3>$1</h3>')
.replace(/^> (.*?$)/gm, '<blockquote>$1</blockquote>')
.replace(/~~([\s\S]*?)~~/g, '<del>$1</del>')
.replace(/(?:https?|ftp):\/\/[^\s(){}[\]]+/g, function (url) {
return `<a href="${url.replace(/<\/?blockquote>/g, '')}" target="_blank">${url}</a>`;
})
.replace(/<:(\w+):(\d+)>/g, '<img src="https://cdn.discordapp.com/emojis/$2.webp?size=96&quality=lossless" alt="$1" width="16px" class="emoji">')
.replace(/<a:(\w+):(\d+)>/g, '<img src="https://cdn.discordapp.com/emojis/$2.gif?size=96&quality=lossless" alt="$1" width="16px" class="emoji">')
.replace(/\n/g, '<br>');
var isEmoji = /^[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]+$/u.test(content);
if (isEmoji) {
postContentText.classList.add("big");
}
postContentText.innerHTML = textContent;
postContentText.querySelectorAll('p a').forEach(link => {
const url = link.getAttribute('href');
const fileExtension = url.split('.').pop().toLowerCase();
const fileDomain = url.includes('tenor.com/view');
if ((['png', 'jpg', 'jpeg', 'webp', 'gif', 'mp4', 'webm', 'mov', 'm4v'].includes(fileExtension)) || fileDomain) {
link.classList.add('attachment');
link.innerHTML = '<svg class="icon_ecf39b icon__13ad2" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24"><path fill="currentColor" d="M10.57 4.01a6.97 6.97 0 0 1 9.86 0l.54.55a6.99 6.99 0 0 1 0 9.88l-7.26 7.27a1 1 0 0 1-1.42-1.42l7.27-7.26a4.99 4.99 0 0 0 0-7.06L19 5.43a4.97 4.97 0 0 0-7.02 0l-8.02 8.02a3.24 3.24 0 1 0 4.58 4.58l6.24-6.24a1.12 1.12 0 0 0-1.58-1.58l-3.5 3.5a1 1 0 0 1-1.42-1.42l3.5-3.5a3.12 3.12 0 1 1 4.42 4.42l-6.24 6.24a5.24 5.24 0 0 1-7.42-7.42l8.02-8.02Z" class=""></path></svg><span> attachments</span>';
} else {
// find a better method to do this
const socregex = {
'twitter': /twitter\.com\/@(\w+)/,
'discord_user': /discord\.com\/users\/(\w+)/,
'discord_channel': /discord\.com\/channels\/(\w+)/,
'discord_server': /discord\.gg\/(\w+)/,
'youtube': /youtube\.com\/@(\w+)/,
'instagram': /instagram\.com\/(\w+)/,
'facebook': /facebook\.com\/(\w+)/,
'scratch': /scratch\.mit.edu\/users\/(\w+)/,
'meower_user': /app.meower\.org\/users\/(\w+)/,
'meower_share': /meo-32r\.pages\.dev\/share\?id=([\w-]+)/
};
const socialmedicns = {
'twitter': 'twitter_1x.png',
'discord_user': 'discord_1x.png',
'discord_channel': 'discord_1x.png',
'discord_server': 'discord_1x.png',
'youtube': 'youtube_1x.png',
'instagram': 'instagram_1x.png',
'facebook': 'facebook_1x.png',
'scratch': 'scratch_1x.png',
'meower_user': 'meo_1x.png',
'meower_share': 'meo_1x.png'
};
for (const [platform, regex] of Object.entries(socregex)) {
const match = url.match(regex);
if (match) {
const username = match[1];
link.classList.add('ext-link');
const icon = socialmedicns[platform];
link.innerHTML = `<span class="ext-link-wrapper"><span class="link-icon-wrapper"><img width="14px" class="ext-icon" src="images/links/${icon}"></span>${username}</span>`;
}
}
}
});
wrapperDiv.appendChild(postContentText);
var links = content.match(/(?:https?|ftp):\/\/[^\s(){}[\]]+/g);
if (links) {
links.forEach(link => {
var baseURL = link.split('?')[0];
var fileExtension = baseURL.split('.').pop().toLowerCase();
var embeddedElement;
if (['png', 'jpg', 'jpeg', 'webp', 'gif'].includes(fileExtension)) {
var imgElement = document.createElement("img");
imgElement.setAttribute("src", baseURL);
imgElement.setAttribute("style", "max-width: 300px; max-height: 300px");
imgElement.classList.add("embed");
var imgLink = document.createElement("a");
imgLink.setAttribute("href", baseURL);
imgLink.setAttribute("target", "_blank");
imgLink.appendChild(imgElement);
embeddedElement = imgLink;
} else if (['mp4', 'webm', 'mov', 'mp3', 'wav', 'ogg'].includes(fileExtension)) {
embeddedElement = document.createElement("video");
embeddedElement.setAttribute("src", baseURL);
embeddedElement.setAttribute("controls", "controls");
embeddedElement.setAttribute("style", "max-width: 300px;");
embeddedElement.classList.add("embed");
}
var youtubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/;
if (youtubeRegex.test(link)) {
var match = link.match(youtubeRegex);
var videoId = match[4];
embeddedElement = document.createElement("iframe");
embeddedElement.setAttribute("width", "100%");
embeddedElement.setAttribute("height", "315");
embeddedElement.setAttribute("style", "max-width:500px;");
embeddedElement.setAttribute("class", "embed");
embeddedElement.setAttribute("src", "https://www.youtube.com/embed/" + videoId);
embeddedElement.setAttribute("title", "YouTube video player");
embeddedElement.setAttribute("frameborder", "0");
embeddedElement.setAttribute("allow", "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share");
embeddedElement.setAttribute("allowfullscreen", "");
} else if (link.includes('open.spotify.com')) {
var spotifyRegex = /track\/([a-zA-Z0-9]+)/;
var match = link.match(spotifyRegex);
if (match) {
var trackId = match[1];
var embeddedElement = document.createElement("iframe");
embeddedElement.setAttribute("style", "border-radius: 12px;max-width:500px;");
embeddedElement.setAttribute("src", `https://open.spotify.com/embed/track/${trackId}?utm_source=generator`);
embeddedElement.setAttribute("width", "100%");
embeddedElement.setAttribute("height", "80px");
embeddedElement.setAttribute("frameBorder", "0");
embeddedElement.setAttribute("allowfullscreen", "");
embeddedElement.setAttribute("allow", "autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture");
embeddedElement.setAttribute("loading", "lazy");
embeddedElement.classList.add("embed");
}
} else if (link.includes('tenor.com')) {
var tenorRegex = /\d+$/;
var tenorMatch = link.match(tenorRegex);
var postId = tenorMatch ? tenorMatch[0] : null;
if (postId) {
var embeddedElement = document.createElement('div');
embeddedElement.className = 'tenor-gif-embed';
embeddedElement.setAttribute('data-postid', postId);
embeddedElement.setAttribute('data-share-method', 'host');
embeddedElement.setAttribute('data-style', 'width: 100%; height: 100%; border-radius: 5px; max-width: 400px; aspect-ratio: 1 / 1; max-height: 400px;');
embeddedElement.classList.add("embed");
postContainer.appendChild(embeddedElement);
var scriptTag = document.createElement('script');
scriptTag.setAttribute('type', 'text/javascript');
scriptTag.setAttribute('src', 'embed.js');
postContainer.appendChild(scriptTag);
}
}
if (embeddedElement) {
wrapperDiv.appendChild(embeddedElement);
}
});
}
}
loadPfp(user)
.then(pfpElement => {
if (pfpElement) {
pfpDiv.appendChild(pfpElement);
//thx stackoverflow
pfpCache[user] = pfpElement.cloneNode(true);
}
});
postContainer.appendChild(pfpDiv);
postContainer.appendChild(wrapperDiv);
var pageContainer = document.getElementById("msgs");
if (pageContainer.firstChild) {
pageContainer.insertBefore(postContainer, pageContainer.firstChild);
} else {
pageContainer.appendChild(postContainer);
}
}
function loadPfp(username) {
return new Promise((resolve, reject) => {
if (pfpCache[username]) {
resolve(pfpCache[username].cloneNode(true));
} else {
let pfpElement; //make pfp element EXIST
fetch(`https://api.meower.org/users/${username}`)
.then(userResp => userResp.json())
.then(userData => {
if (userData.avatar) {
const pfpurl = `https://uploads.meower.org/icons/${userData.avatar}`;
pfpElement = document.createElement("img");
pfpElement.setAttribute("src", pfpurl);
pfpElement.setAttribute("alt", "User Avatar");
pfpElement.classList.add("avatar");
if (userData.avatar_color) {
pfpElement.style.border = `3px solid #${userData.avatar_color}`;
}
} else if (userData.pfp_data) {
const pfpurl = `images/avatars/icon_${userData.pfp_data - 1}.svg`;
pfpElement = document.createElement("img");
pfpElement.setAttribute("src", pfpurl);
pfpElement.setAttribute("alt", "User Avatar");
pfpElement.classList.add("avatar");
} else {
console.error("No avatar or pfp_data available for: ", username);
resolve(null);
}
if (pfpElement) {
pfpCache[username] = pfpElement.cloneNode(true);
}
resolve(pfpElement);
})
.catch(error => {
console.error("Failed to fetch:", error);
resolve(null);
});
}
});
}
async function loadreply(replyid) {
try {
const replyresp = await fetch(`https://api.meower.org/posts?id=${replyid}`, {
headers: {token: localStorage.getItem("token")}
});
const replydata = await replyresp.json();
const replycontainer = document.createElement("div");
replycontainer.classList.add("reply");
replycontainer.innerHTML = `<p style='font-weight:bold;margin: 10px 0 10px 0;'>${replydata.u}</p><p style='margin: 10px 0 10px 0;'>${replydata.p}</p>`;
return replycontainer;
} catch (error) {
console.error("Error fetching reply:", error);
return document.createElement("p");
}
}
window.onload = loadsharedpost();
</script>
</body>
</html>