misskey/packages/misskey-js/src/acct.ts

68 lines
2.1 KiB
TypeScript

export type Acct = {
username: string;
host: string | null;
};
export function correctAcct(acct: Acct, localHostname?: string): Acct {
const result = { ...acct };
if (!acct.host) {
result.host = null;
} else if (localHostname && acct.host === localHostname) {
result.host = null;
}
return result;
}
export function parse(acct: string): Acct {
let acctWithNoPrefix = acct;
if (acct.startsWith('@')) {
acctWithNoPrefix = acct.substring(1);
} else if (acct.startsWith('acct:')) {
acctWithNoPrefix = acct.substring(5);
}
const split = acctWithNoPrefix.split('@', 2);
return { username: split[0], host: split[1] || null };
}
export function parseUrl(str: string): Acct {
const url = new URL(str);
const splited = url.pathname.split('/');
let path = splited.pop();
if (path === '') path = splited.pop(); // If the last segment is empty due to a trailing '/', use the previous segment
if (!path) throw new Error('This url is not acct like.');
if (!path.startsWith('@')) throw new Error('This url is not acct like.');
if (path.length <= 1) throw new Error('This url is not acct like.');
const split = path.split('@', 3); // ['', 'username', 'other.example.com']
return { username: split[1], host: split[2] || url.hostname };
}
/**
* Parses a string and returns an Acct object.
* @param acct String to parse
* The string should be in one of the following formats:
* * At-mark style: `@username@example.com`
* * Starts with `acct:`: `acct:username@example.com`
* * URL style: `https://example.com/@username`, `https://self.example.com/@username@other.example.com`
* @param localHostname If provided and matches the host found in acct, the returned `host` will be set to `null`.
* @returns Acct object
*/
export function parseAcctOrUrl(acct: string, localHostname?: string): Acct {
if (acct.startsWith('https://') || acct.startsWith('http://')) {
// url style
return correctAcct(parseUrl(acct), localHostname);
}
// acct style
return correctAcct(parse(acct), localHostname);
}
export function toString(acct: Acct): string {
return acct.host == null ? acct.username : `${acct.username}@${acct.host}`;
}