Whalebird-desktop-client-ma.../renderer/utils/statusParser.ts

130 lines
4.1 KiB
TypeScript

import { Entity } from 'megalodon'
export type ParsedAccount = {
username: string
acct: string
url: string
}
export function findLink(target: HTMLElement | null, parentClassName: string): string | null {
if (!target) {
return null
}
if (target.localName === 'a') {
return (target as HTMLLinkElement).href
}
if (target.parentNode === undefined || target.parentNode === null) {
return null
}
const parent = target.parentNode as HTMLElement
if (parent.getAttribute && parent.getAttribute('class') === parentClassName) {
return null
}
return findLink(parent, parentClassName)
}
export function findTag(target: HTMLElement, parentClass = 'toot'): string | null {
if (!target || !target.getAttribute) {
return null
}
const targetClass = target.getAttribute('class')
if (targetClass && targetClass.includes('hashtag')) {
return parseTag((target as HTMLLinkElement).href)
}
// In Pleroma, link does not have class.
// So I have to check URL.
const link = target as HTMLLinkElement
if (link.href && link.href.match(/^https:\/\/[a-zA-Z0-9-.]+\/(tag|tags)\/.+/)) {
return parseTag(link.href)
}
if (target.parentNode === undefined || target.parentNode === null) {
return null
}
const parent = target.parentNode as HTMLElement
if (parent.getAttribute && parent.getAttribute('class') === parentClass) {
return null
}
return findTag(parent, parentClass)
}
function parseTag(tagURL: string): string | null {
const res = tagURL.match(/^https:\/\/([a-zA-Z0-9-.]+)\/(tag|tags)\/(.+)/)
if (!res) {
return null
}
return res[3]
}
export function findAccount(target: HTMLElement | null, parentClassName: string): ParsedAccount | null {
if (!target || !target.getAttribute) {
return null
}
const targetClass = target.getAttribute('class')
const link = target as HTMLLinkElement
if (targetClass && targetClass.includes('u-url')) {
if (link.href && link.href.match(/^https:\/\/[a-zA-Z0-9-.]+\/users\/[a-zA-Z0-9-_.]+$/)) {
return parsePleromaAccount(link.href)
} else {
return parseMastodonAccount(link.href)
}
}
// In Pleroma, link does not have class.
// So we have to check URL.
if (link.href && link.href.match(/^https:\/\/[a-zA-Z0-9-.]+\/@[a-zA-Z0-9-_.]+$/)) {
return parseMastodonAccount(link.href)
}
// Toot URL of Pleroma does not contain @.
if (link.href && link.href.match(/^https:\/\/[a-zA-Z0-9-.]+\/users\/[a-zA-Z0-9-_.]+$/)) {
return parsePleromaAccount(link.href)
}
if (target.parentNode === undefined || target.parentNode === null) {
return null
}
const parent = target.parentNode as HTMLElement
if (parent.getAttribute && parent.getAttribute('class') === parentClassName) {
return null
}
return findAccount(parent, parentClassName)
}
export function parseMastodonAccount(accountURL: string): ParsedAccount | null {
const res = accountURL.match(/^https:\/\/([a-zA-Z0-9-.]+)\/(@[a-zA-Z0-9-_.]+)$/)
if (!res) {
return null
}
const domainName = res[1]
const accountName = res[2]
return {
username: accountName,
acct: `${accountName}@${domainName}`,
url: accountURL
}
}
export function parsePleromaAccount(accountURL: string): ParsedAccount | null {
const res = accountURL.match(/^https:\/\/([a-zA-Z0-9-.]+)\/users\/([a-zA-Z0-9-_.]+)$/)
if (!res) {
return null
}
const domainName = res[1]
const accountName = res[2]
return {
username: `@${accountName}`,
acct: `@${accountName}@${domainName}`,
url: accountURL
}
}
export function accountMatch(findAccounts: Array<Entity.Account>, parsedAccount: ParsedAccount, domain: string): Entity.Account | false {
const account = findAccounts.find(a => `@${a.acct}` === parsedAccount.acct)
if (account) return account
const pleromaUser = findAccounts.find(a => a.acct === parsedAccount.acct)
if (pleromaUser) return pleromaUser
const localUser = findAccounts.find(a => `@${a.username}@${domain}` === parsedAccount.acct)
if (localUser) return localUser
const user = findAccounts.find(a => a.url === parsedAccount.url)
if (!user) return false
return user
}