fix plc
This commit is contained in:
@@ -20,15 +20,49 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"maxLength": 1000000,
|
"maxLength": 1000000,
|
||||||
"maxGraphemes": 100000,
|
"maxGraphemes": 100000,
|
||||||
"description": "The content of the post."
|
"description": "The content of the post (markdown)."
|
||||||
},
|
},
|
||||||
"createdAt": {
|
"createdAt": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "datetime",
|
"format": "datetime",
|
||||||
"description": "Client-declared timestamp when this post was originally created."
|
"description": "Client-declared timestamp when this post was originally created."
|
||||||
|
},
|
||||||
|
"lang": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 10,
|
||||||
|
"description": "Language code of the original content (e.g., 'ja', 'en')."
|
||||||
|
},
|
||||||
|
"translations": {
|
||||||
|
"type": "ref",
|
||||||
|
"ref": "#translationMap",
|
||||||
|
"description": "Translations of the post in other languages."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"translationMap": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Map of language codes to translations.",
|
||||||
|
"properties": {
|
||||||
|
"en": { "type": "ref", "ref": "#translation" },
|
||||||
|
"ja": { "type": "ref", "ref": "#translation" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"translation": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "A translation of a post.",
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 3000,
|
||||||
|
"maxGraphemes": 300
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 1000000,
|
||||||
|
"maxGraphemes": 100000
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
68
public/.well-known/lexicon/ai/syui/log/post.json
Normal file
68
public/.well-known/lexicon/ai/syui/log/post.json
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"lexicon": 1,
|
||||||
|
"id": "ai.syui.log.post",
|
||||||
|
"defs": {
|
||||||
|
"main": {
|
||||||
|
"type": "record",
|
||||||
|
"description": "Record containing a blog post.",
|
||||||
|
"key": "tid",
|
||||||
|
"record": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["title", "content", "createdAt"],
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 3000,
|
||||||
|
"maxGraphemes": 300,
|
||||||
|
"description": "The title of the post."
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 1000000,
|
||||||
|
"maxGraphemes": 100000,
|
||||||
|
"description": "The content of the post (markdown)."
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "datetime",
|
||||||
|
"description": "Client-declared timestamp when this post was originally created."
|
||||||
|
},
|
||||||
|
"lang": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 10,
|
||||||
|
"description": "Language code of the original content (e.g., 'ja', 'en')."
|
||||||
|
},
|
||||||
|
"translations": {
|
||||||
|
"type": "ref",
|
||||||
|
"ref": "#translationMap",
|
||||||
|
"description": "Translations of the post in other languages."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"translationMap": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Map of language codes to translations.",
|
||||||
|
"properties": {
|
||||||
|
"en": { "type": "ref", "ref": "#translation" },
|
||||||
|
"ja": { "type": "ref", "ref": "#translation" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"translation": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "A translation of a post.",
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 3000,
|
||||||
|
"maxGraphemes": 300
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 1000000,
|
||||||
|
"maxGraphemes": 100000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,17 @@
|
|||||||
import { describeRepo, listRecordsRaw, getRecordRaw, fetchLexicon, resolveHandle, getServiceInfo, resolvePds, getPlc } from '../lib/api.js'
|
import { describeRepo, listRecordsRaw, getRecordRaw, fetchLexicon, resolveHandle, getServiceInfo, resolvePds, getPlcForPds } from '../lib/api.js'
|
||||||
import { deleteRecord } from '../lib/auth.js'
|
import { deleteRecord } from '../lib/auth.js'
|
||||||
import { escapeHtml } from '../lib/utils.js'
|
import { escapeHtml } from '../lib/utils.js'
|
||||||
|
import type { Networks } from '../types.js'
|
||||||
|
|
||||||
|
// Cache networks config
|
||||||
|
let networksConfig: Networks | null = null
|
||||||
|
|
||||||
|
async function loadNetworks(): Promise<Networks> {
|
||||||
|
if (networksConfig) return networksConfig
|
||||||
|
const res = await fetch('/networks.json')
|
||||||
|
networksConfig = await res.json()
|
||||||
|
return networksConfig!
|
||||||
|
}
|
||||||
|
|
||||||
function extractRkey(uri: string): string {
|
function extractRkey(uri: string): string {
|
||||||
const parts = uri.split('/')
|
const parts = uri.split('/')
|
||||||
@@ -8,13 +19,15 @@ function extractRkey(uri: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function renderServices(did: string, handle: string): Promise<string> {
|
async function renderServices(did: string, handle: string): Promise<string> {
|
||||||
const [collections, pds] = await Promise.all([
|
const [collections, pds, networks] = await Promise.all([
|
||||||
describeRepo(did),
|
describeRepo(did),
|
||||||
resolvePds(did)
|
resolvePds(did),
|
||||||
|
loadNetworks()
|
||||||
])
|
])
|
||||||
|
|
||||||
// Server info section
|
// Server info section - use PLC based on PDS
|
||||||
const plcUrl = `${getPlc()}/${did}/log`
|
const plc = getPlcForPds(pds, networks)
|
||||||
|
const plcUrl = `${plc}/${did}/log`
|
||||||
const serverHtml = `
|
const serverHtml = `
|
||||||
<div class="server-info">
|
<div class="server-info">
|
||||||
<h3>Server</h3>
|
<h3>Server</h3>
|
||||||
|
|||||||
@@ -14,6 +14,33 @@ export function getPlc(): string {
|
|||||||
return networkConfig?.plc || 'https://plc.directory'
|
return networkConfig?.plc || 'https://plc.directory'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get PLC URL based on PDS endpoint
|
||||||
|
export function getPlcForPds(pds: string, networks: Record<string, { plc: string; bsky: string; web?: string }>): string {
|
||||||
|
// Check if PDS matches any network
|
||||||
|
for (const [_key, config] of Object.entries(networks)) {
|
||||||
|
// Match by domain (e.g., "https://syu.is" or "https://bsky.syu.is")
|
||||||
|
try {
|
||||||
|
const pdsHost = new URL(pds).hostname
|
||||||
|
const bskyHost = new URL(config.bsky).hostname
|
||||||
|
// Check if PDS host matches network's bsky host
|
||||||
|
if (pdsHost === bskyHost || pdsHost.endsWith('.' + bskyHost)) {
|
||||||
|
return config.plc
|
||||||
|
}
|
||||||
|
// Also check web host if available
|
||||||
|
if (config.web) {
|
||||||
|
const webHost = new URL(config.web).hostname
|
||||||
|
if (pdsHost === webHost || pdsHost.endsWith('.' + webHost)) {
|
||||||
|
return config.plc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Default to plc.directory
|
||||||
|
return 'https://plc.directory'
|
||||||
|
}
|
||||||
|
|
||||||
function getBsky(): string {
|
function getBsky(): string {
|
||||||
return networkConfig?.bsky || 'https://public.api.bsky.app'
|
return networkConfig?.bsky || 'https://public.api.bsky.app'
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user