+222
-97
index.html
+222
-97
index.html
···
33
33
};
34
34
window.isXrpcErr = e => e instanceof ClientResponseError;
35
35
36
+
window.isBeforeNow = iso => new Date(iso) < new Date();
37
+
36
38
window.dnsResolver = new DohJsonHandleResolver({
37
39
dohUrl: 'https://mozilla.cloudflare-dns.com/dns-query',
38
40
});
···
87
89
hostname: 'relay1.us-west.bsky.network',
88
90
},
89
91
];
92
+
93
+
window.regionalModAccounts = [ // https://github.com/mary-ext/atproto-scraping?tab=readme-ov-file#bluesky-labelers
94
+
'https://mod-br.bsky.app',
95
+
'https://mod-de.bsky.app',
96
+
'https://mod-in.bsky.app',
97
+
'https://mod-ru.bsky.app',
98
+
'https://mod-tr.bsky.app',
99
+
];
100
+
101
+
window.bskyAccountDeathLabels = {
102
+
['needs-review']: 'Automated action, cleared by manual review from Bluesky moderation team. Your content can ve accessed via direct links on Bluesky, but invisible in feeds and replies to posts.',
103
+
['!suspend']: 'Moderation action from Bluesky moderation team. Makes your content inaccessible on the Bluesky app.',
104
+
['!takedown']: 'Moderation action from Bluesky moderation team. Makes your content inaccessible on the Bluesky app.',
105
+
['!hide']: 'Almost always used with !takedown, makes your content inaccessible on the Bluesky app.',
106
+
// other labels shouldn't cause problems that make you think your pds is broken
107
+
// 'spam': just hides replies by default + makes your posts click-through
108
+
// 'intolerant', etc: similar to spam
109
+
};
110
+
111
+
if (window.blehYeahReady) blehYeahReady();
112
+
else window.yeahBlehIsReady = true;
90
113
</script>
91
114
115
+
<style>
116
+
body:not(.ready) .hide-until-ready,
117
+
body.ready .show-until-ready {
118
+
display: none;
119
+
}
120
+
</style>
121
+
92
122
<script>
93
123
document.addEventListener('alpine:init', () => {
124
+
if (window.yeahBlehIsReady) {
125
+
document.body.classList.add('ready');
126
+
} else {
127
+
window.blehYeahReady = () => document.body.classList.add('ready');
128
+
}
129
+
94
130
Alpine.data('debug', () => ({
95
131
// form input
96
132
identifier: '',
···
275
311
});
276
312
this.status = data.status;
277
313
} catch(e) {
278
-
if (relay.missingApis['com.atproto.sync.getHostStatus']) {
314
+
if (relay.missingApis?.['com.atproto.sync.getHostStatus']) {
279
315
this.error = 'Can\'t check';
280
-
this.expectedErrorInfo = relay.missingApis['com.atproto.sync.getHostStatus'];
316
+
this.expectedErrorInfo = relay.missingApis?.['com.atproto.sync.getHostStatus'];
281
317
} else if (window.isXrpcErr(e)) {
282
318
this.error = e.error;
283
319
} else {
···
456
492
params: { did },
457
493
});
458
494
} catch(e) {
459
-
if (relay.missingApis['com.atproto.sync.getRepoStatus']) {
495
+
if (relay.missingApis?.['com.atproto.sync.getRepoStatus']) {
460
496
this.error = 'Can\'t check';
461
-
this.expectedErrorInfo = relay.missingApis['com.atproto.sync.getRepoStatus'];
497
+
this.expectedErrorInfo = relay.missingApis?.['com.atproto.sync.getRepoStatus'];
462
498
} else if (window.isXrpcErr(e)) {
463
499
this.error = e.error;
464
500
} else {
···
482
518
}
483
519
}));
484
520
521
+
Alpine.data('modLabels', did => ({
522
+
loading: false,
523
+
error: null,
524
+
regionalErrors: [],
525
+
labels: [],
526
+
527
+
async init() {
528
+
this.loading = true;
529
+
this.error = null;
530
+
this.regionalErrors = [];
531
+
this.labels = [];
532
+
533
+
const query = window.SimpleQuery('https://mod.bsky.app');
534
+
535
+
try {
536
+
const res = await query('com.atproto.label.queryLabels', {
537
+
params: { uriPatterns: [did] },
538
+
});
539
+
this.labels = res.labels ?? [];
540
+
// TODO: handle cursors?
541
+
542
+
for (const region of window.regionalModAccounts) {
543
+
// intentionally no await, these come in async
544
+
// (...and could get messy if we start re-checking labels before they're done)
545
+
this.checkRegionLabels(region);
546
+
}
547
+
} catch (e) {
548
+
if (window.isXrpcErr(e)) {
549
+
this.error = e.error;
550
+
} else {
551
+
this.error = 'Failed to check (see console)';
552
+
console.error(e);
553
+
}
554
+
}
555
+
this.loading = false;
556
+
},
557
+
558
+
async checkRegionLabels(labeler) {
559
+
const query = window.SimpleQuery(labeler);
560
+
try {
561
+
const res = await query('com.atproto.label.queryLabels', {
562
+
params: { uriPatterns: [did] },
563
+
});
564
+
if (res?.labels?.length > 0) this.labels.push(...res.labels);
565
+
} catch (e) {
566
+
if (window.isXrpcErr(e)) {
567
+
this.regionalErrors.push(`${labeler}: ${e.error}`);
568
+
} else {
569
+
this.regionalErrors.push(`Failed to check ${labeler} (see console)`);
570
+
console.error(`labeler: ${labeler}`, e);
571
+
}
572
+
}
573
+
}
574
+
}));
575
+
485
576
Alpine.data('pdsHistory', (did, currentPds) => ({
486
577
loading: false,
487
578
error: null,
···
567
658
this.loading = false;
568
659
},
569
660
}));
570
-
571
-
Alpine.data('modLabels', (did) => ({
572
-
loading: false,
573
-
error: null,
574
-
labels: [],
575
-
576
-
async init() {
577
-
this.loading = true;
578
-
this.error = null;
579
-
this.labels = [];
580
-
try {
581
-
const res = await fetch(`https://mod.bsky.app/xrpc/com.atproto.label.queryLabels?uriPatterns=${did}`);
582
-
if (res.ok) {
583
-
const response = await res.json();
584
-
if (response.labels && response.labels.length > 0) {
585
-
this.labels = response.labels;
586
-
}
587
-
} else {
588
-
this.error = `${res.status}: ${await res.text()}`;
589
-
}
590
-
} catch (e) {
591
-
this.error = 'failed to get labels from mod.bsky.app';
592
-
console.error(e);
593
-
}
594
-
this.loading = false;
595
-
},
596
-
}));
597
661
})
598
662
</script>
599
663
</head>
···
601
665
<div class="hero bg-base-200 p-8">
602
666
<div class="hero-content flex-col">
603
667
<h1 class="text-2xl mb-8">PDS Debugger</h1>
604
-
<form @submit.prevent="await diagnose()">
668
+
<p class="show-until-ready"><em>Loading…</em></p>
669
+
<form class="hide-until-ready" @submit.prevent="await diagnose()">
605
670
<label class="text-sm text-primary" for="identifier">
606
671
atproto handle, DID, or HTTPS PDS URL
607
672
</label>
···
880
945
></a>
881
946
</td>
882
947
</tr>
948
+
<!--<tr>
949
+
<td
950
+
class="text-sm"
951
+
x-data="repoMonitor(did, pds)"
952
+
>
953
+
<button
954
+
class="btn btn-xs btn-success"
955
+
>Start live monitoring</button>
956
+
</td>
957
+
</tr>-->
883
958
</tbody>
884
959
</table>
885
960
</div>
···
965
1040
>ahead</span>
966
1041
</td>
967
1042
</template>
1043
+
<template x-if="!revStatus(state && state.rev)">
1044
+
<td></td>
1045
+
</template>
968
1046
</tr>
969
1047
</template>
970
1048
</tbody>
971
1049
</table>
972
1050
</div>
973
1051
1052
+
<div x-data="modLabels(did)">
1053
+
<h3 class="text-lg mt-3">
1054
+
Labels
1055
+
</h3>
1056
+
<div class="overflow-x-auto">
1057
+
<table class="table table-xs">
1058
+
<tbody>
1059
+
<template x-if="loading">
1060
+
<tr>
1061
+
<td>Loading…</td>
1062
+
</tr>
1063
+
</template>
1064
+
<template x-if="error">
1065
+
<tr>
1066
+
<td>Error: <span x-text="error"></span></td>
1067
+
</tr>
1068
+
</template>
1069
+
<template x-if="!loading && !error && labels.length === 0">
1070
+
<tr>
1071
+
<td class="text-xs">
1072
+
<em>No Bluesky moderation labels found</em>
1073
+
</td>
1074
+
</tr>
1075
+
</template>
1076
+
<template x-for="label in labels">
1077
+
<template x-if="!!label">
1078
+
<tr x-data="{ expired: isBeforeNow(label.exp) }">
1079
+
<td>
1080
+
<span x-show="label.neg">removed</span>
1081
+
<code
1082
+
x-text="label.cts.split('T')[0]"
1083
+
:title="label.cts"
1084
+
></code>
1085
+
</td>
1086
+
<td>
1087
+
<template x-if="!!label.exp">
1088
+
<span x-text="expired ? 'expired' : 'expires'"></span>
1089
+
<code
1090
+
x-text="label.exp.split('T')[0]"
1091
+
:title="label.exp"
1092
+
></code>
1093
+
</template>
1094
+
</td>
1095
+
<td>
1096
+
<code
1097
+
x-text="label.val"
1098
+
class="badge badge-sm badge-soft"
1099
+
:class="(label.neg || expired)
1100
+
? 'badge-neutral line-through'
1101
+
: !!window.bskyAccountDeathLabels[label.val]
1102
+
? 'badge-warning'
1103
+
: 'badge-info'"
1104
+
:title="label.neg
1105
+
? 'label negated'
1106
+
: expired
1107
+
? 'label expired'
1108
+
: window.bskyAccountDeathLabels[label.val] ?? ''"
1109
+
></code>
1110
+
</td>
1111
+
<td
1112
+
x-data="didToHandle(label.src)"
1113
+
x-intersect:enter.once="load"
1114
+
>
1115
+
<span x-show="loading">Loading…</span>
1116
+
<span x-show="error !== null" x-text="error"></span>
1117
+
<a
1118
+
href="#"
1119
+
class="link"
1120
+
@click.prevent="goto(handle)"
1121
+
x-show="handle !== null"
1122
+
x-text="`@${handle}`"
1123
+
></a>
1124
+
</td>
1125
+
</tr>
1126
+
</template>
1127
+
</template>
1128
+
</tbody>
1129
+
</table>
1130
+
</div>
1131
+
<template x-for="error in regionalErrors">
1132
+
<p
1133
+
x-text="error"
1134
+
class="text-xs text-warning"
1135
+
></p>
1136
+
</template>
1137
+
</div>
1138
+
974
1139
<template x-if="did.startsWith('did:plc:')">
975
1140
<div x-data="pdsHistory(did, pds)">
976
1141
<h3 class="text-lg mt-3">
···
1042
1207
</div>
1043
1208
</div>
1044
1209
</template>
1045
-
1046
-
<template x-if="did != null">
1047
-
<div x-data="modLabels(did)">
1048
-
<h3 class="text-lg mt-3">
1049
-
Labels from Bluesky (mod.bsky.app)
1050
-
</h3>
1051
-
<div class="overflow-x-auto">
1052
-
<table class="table table-xs">
1053
-
<template x-if="!loading && !error && labels.length !== 0">
1054
-
<thead>
1055
-
<tr>
1056
-
<th>created</th>
1057
-
<th>exp</th>
1058
-
<th>label</th>
1059
-
</tr>
1060
-
</thead>
1061
-
</template>
1062
-
<tbody>
1063
-
<template x-if="loading">
1064
-
<tr>
1065
-
<td>Loading…</td>
1066
-
</tr>
1067
-
</template>
1068
-
<template x-if="error">
1069
-
<tr>
1070
-
<td>Error: <span x-text="error"></span></td>
1071
-
</tr>
1072
-
</template>
1073
-
<template x-if="!loading && !error && labels.length === 0">
1074
-
<tr>
1075
-
<td class="text-sm">
1076
-
<em>no labels applied by mod.bsky.app</em>
1077
-
</td>
1078
-
</tr>
1079
-
</template>
1080
-
<template x-for="label in labels">
1081
-
<tr>
1082
-
<td>
1083
-
<code x-text="label.cts.split('.')[0]"></code>
1084
-
</td>
1085
-
<td>
1086
-
<code x-text="label.exp.split('.')[0]"></code>
1087
-
</td>
1088
-
1089
-
<td>
1090
-
<span
1091
-
x-text="label.val"
1092
-
class="badge badge-sm badge-soft badge-warning"
1093
-
></span>
1094
-
</td>
1095
-
1096
-
</tr>
1097
-
</template>
1098
-
</tbody>
1099
-
</table>
1100
-
</div>
1101
-
</div>
1102
-
</template>
1103
1210
</div>
1104
1211
</template>
1105
1212
</div>
···
1211
1318
1212
1319
<div class="footer text-xs sm:footer-horizontal text-neutral mt-32 p-8 max-w-2xl mx-auto">
1213
1320
<nav>
1214
-
<h3 class="footer-title">Current limitations</h3>
1215
-
<p>PDS hosts without CORS will fail tests</p>
1216
-
<p>Bluesky relay is missing API endpoints</p>
1217
-
<p>Blacksky relay is also missing API endpoints</p>
1218
-
<p>The requestCrawl button is not well tested</p>
1321
+
<h3 class="footer-title mt-3">Current limitations</h3>
1322
+
<p>PDS hosts without CORS will fail tests.</p>
1323
+
<p>Bluesky relay is missing API endpoints.</p>
1324
+
<p>Blacksky relay is also missing API endpoints.</p>
1325
+
<p>The requestCrawl button is not well tested.</p>
1326
+
1327
+
<h3 class="footer-title mt-3">Future features</h3>
1328
+
<p>Firehose listener</p>
1329
+
<p>URL routing</p>
1330
+
<p>Less strict identity resolution</p>
1219
1331
</nav>
1332
+
1220
1333
<nav>
1334
+
<h3 class="footer-title mt-3">Places</h3>
1335
+
<p><a href="https://tangled.org/microcosm.blue/pds-debug">Source code (tangled.org)</a></p>
1336
+
<p><a href="https://discord.gg/Vwamex5UFS">Discord (microcosm)</a></p>
1337
+
<p><a href="https://pdsmoover.com/">PDS Moover</a></p>
1338
+
<p><a href="https://microcosm.blue">microcosm</a></p>
1221
1339
1222
-
<h3 class="footer-title">Future features</h3>
1223
-
<p>Account label lookup</p>
1340
+
<h3 class="footer-title mt-3">Made by</h3>
1341
+
<p>
1342
+
<a href="https://bsky.app/profile/did:plc:hdhoaan3xa3jiuq4fg4mefid">fig</a>
1343
+
<a href="https://github.com/sponsors/uniphil">(sponsor)</a>
1344
+
</p>
1345
+
<p>
1346
+
<a href="https://bsky.app/profile/did:plc:rnpkyqnmsw4ipey6eotbdnnf">bailey</a>
1347
+
<a href="https://github.com/sponsors/fatfingers23">(sponsor)</a>
1348
+
</p>
1224
1349
</nav>
1225
1350
</div>
1226
1351
+5
readme.md
+5
readme.md
+13
useful-accounts.txt
+13
useful-accounts.txt
···
1
+
some accounts that show things useful for testing the debugger
2
+
3
+
4
+
Labels
5
+
6
+
- did:plc:bnwrgnvwkg2n5cbvk4xodb3h | !hide | no other labels
7
+
- did:plc:qhl3vg5tmwey536z2fil2lrh | !hide | from moderation-tr.bsky.app
8
+
- did:plc:fsmaoqqnm6knqh4cuphb4jow | !hide, ~!takedown | takedown negated
9
+
- did:plc:iv3yod6zf2j4zaakq6qyiz46 | !takedown |
10
+
- did:plc:nwrcwcrhpkgrqqvkg3lmaqky | ~needs-review, ~!takedown | both negated
11
+
- did:plc:2tinwgqvf4asiwh36ii6ko7l | needs-review | expired
12
+
- did:plc:5plqrpw3x6j5wzaosssqams7 | spam | no other labels
13
+
- did:plc:tqww7jdpqx5tb3w435fugmxi | intolerant |