enhance image detection and proxy
This commit is contained in:
		
							parent
							
								
									059d8d68ac
								
							
						
					
					
						commit
						3c711b6083
					
				@ -1,5 +1,5 @@
 | 
			
		||||
import { createHmac } from 'node:crypto'
 | 
			
		||||
import { extractUrls } from '../../lib/md'
 | 
			
		||||
import { extractUrls } from '../../../lib/md'
 | 
			
		||||
 | 
			
		||||
const IMGPROXY_URL = process.env.NEXT_PUBLIC_IMGPROXY_URL
 | 
			
		||||
const IMGPROXY_SALT = process.env.IMGPROXY_SALT
 | 
			
		||||
@ -20,7 +20,7 @@ const createImageProxyUrl = url => {
 | 
			
		||||
  const b64Url = Buffer.from(url, 'utf-8').toString('base64url')
 | 
			
		||||
  const target = `${processingOptions}/${b64Url}`
 | 
			
		||||
  const signature = sign(target)
 | 
			
		||||
  return `${IMGPROXY_URL}/${signature}${target}`
 | 
			
		||||
  return `${IMGPROXY_URL}${signature}${target}`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const isImageURL = async url => {
 | 
			
		||||
@ -35,13 +35,13 @@ const isImageURL = async url => {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const useImageProxy = async text => {
 | 
			
		||||
export const proxyImages = async text => {
 | 
			
		||||
  const urls = extractUrls(text)
 | 
			
		||||
  for (const url of urls) {
 | 
			
		||||
    if (url.startsWith(IMGPROXY_URL)) continue
 | 
			
		||||
    if (!(await isImageURL(url))) continue
 | 
			
		||||
    const proxyUrl = createImageProxyUrl(url)
 | 
			
		||||
    text = text.replace(new RegExp(url, 'g'), proxyUrl)
 | 
			
		||||
    text = text.replaceAll(url, proxyUrl)
 | 
			
		||||
  }
 | 
			
		||||
  return text
 | 
			
		||||
}
 | 
			
		||||
@ -13,7 +13,7 @@ import { parse } from 'tldts'
 | 
			
		||||
import uu from 'url-unshort'
 | 
			
		||||
import { amountSchema, bountySchema, commentSchema, discussionSchema, jobSchema, linkSchema, pollSchema, ssValidate } from '../../lib/validate'
 | 
			
		||||
import { sendUserNotification } from '../webPush'
 | 
			
		||||
import { useImageProxy } from '../imgproxy'
 | 
			
		||||
import { proxyImages } from './imgproxy'
 | 
			
		||||
 | 
			
		||||
async function comments (me, models, id, sort) {
 | 
			
		||||
  let orderBy
 | 
			
		||||
@ -1251,8 +1251,8 @@ export const updateItem = async (parent, { id, data: { sub, title, url, text, bo
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  url = await useImageProxy(url)
 | 
			
		||||
  text = await useImageProxy(text)
 | 
			
		||||
  url = await proxyImages(url)
 | 
			
		||||
  text = await proxyImages(text)
 | 
			
		||||
 | 
			
		||||
  const [item] = await serialize(models,
 | 
			
		||||
    models.$queryRaw(
 | 
			
		||||
@ -1286,8 +1286,8 @@ const createItem = async (parent, { sub, title, url, text, boost, forward, bount
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  url = await useImageProxy(url)
 | 
			
		||||
  text = await useImageProxy(text)
 | 
			
		||||
  url = await proxyImages(url)
 | 
			
		||||
  text = await proxyImages(text)
 | 
			
		||||
 | 
			
		||||
  const [item] = await serialize(
 | 
			
		||||
    models,
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,7 @@ import PollIcon from '../svgs/bar-chart-horizontal-fill.svg'
 | 
			
		||||
import BountyIcon from '../svgs/bounty-bag.svg'
 | 
			
		||||
import ActionTooltip from './action-tooltip'
 | 
			
		||||
import Flag from '../svgs/flag-fill.svg'
 | 
			
		||||
import ImageIcon from '../svgs/image-fill.svg'
 | 
			
		||||
import { abbrNum } from '../lib/format'
 | 
			
		||||
import ItemInfo from './item-info'
 | 
			
		||||
 | 
			
		||||
@ -22,6 +23,8 @@ export default function Item ({ item, rank, belowTitle, right, full, children })
 | 
			
		||||
  const titleRef = useRef()
 | 
			
		||||
  const [pendingSats, setPendingSats] = useState(0)
 | 
			
		||||
 | 
			
		||||
  const image = item.url && item.url.startsWith(process.env.NEXT_PUBLIC_IMGPROXY_URL)
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      {rank
 | 
			
		||||
@ -39,16 +42,17 @@ export default function Item ({ item, rank, belowTitle, right, full, children })
 | 
			
		||||
            <Link href={`/items/${item.id}`} passHref>
 | 
			
		||||
              <a ref={titleRef} className={`${styles.title} text-reset mr-2`}>
 | 
			
		||||
                {item.searchTitle ? <SearchTitle title={item.searchTitle} /> : item.title}
 | 
			
		||||
                {item.pollCost && <span> <PollIcon className='fill-grey vertical-align-baseline' height={14} width={14} /></span>}
 | 
			
		||||
                {item.pollCost && <span> <PollIcon className='fill-grey ml-1' height={14} width={14} /></span>}
 | 
			
		||||
                {item.bounty > 0 &&
 | 
			
		||||
                  <span>
 | 
			
		||||
                    <ActionTooltip notForm overlayText={`${abbrNum(item.bounty)} ${item.bountyPaidTo?.length ? 'sats paid' : 'sats bounty'}`}>
 | 
			
		||||
                      <BountyIcon className={`${styles.bountyIcon} ${item.bountyPaidTo?.length ? 'fill-success vertical-align-middle' : 'fill-grey vertical-align-middle'}`} height={16} width={16} />
 | 
			
		||||
                      <BountyIcon className={`${styles.bountyIcon} ${item.bountyPaidTo?.length ? 'fill-success' : 'fill-grey'}`} height={16} width={16} />
 | 
			
		||||
                    </ActionTooltip>
 | 
			
		||||
                  </span>}
 | 
			
		||||
                {image && <span><ImageIcon className='fill-grey ml-2' height={16} width={16} /></span>}
 | 
			
		||||
              </a>
 | 
			
		||||
            </Link>
 | 
			
		||||
            {item.url &&
 | 
			
		||||
            {item.url && !image &&
 | 
			
		||||
              <>
 | 
			
		||||
                {/*  eslint-disable-next-line */}
 | 
			
		||||
                <a
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,8 @@
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
    white-space: normal;
 | 
			
		||||
    max-width: 100%;
 | 
			
		||||
    display: inline-flex;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a.title:visited {
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@ export function extractUrls (md) {
 | 
			
		||||
 | 
			
		||||
  const urls = new Set()
 | 
			
		||||
  visit(tree, ({ type }) => {
 | 
			
		||||
    return type === 'link'
 | 
			
		||||
    return type === 'link' || type === 'image'
 | 
			
		||||
  }, ({ url }) => {
 | 
			
		||||
    urls.add(url)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
@ -94,6 +94,10 @@
 | 
			
		||||
    margin-bottom: .5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.fullItemContainer img {
 | 
			
		||||
    border-radius: .4rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.fullItemContainer:empty {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								svgs/image-fill.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								svgs/image-fill.svg
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 5H4V19L13.2923 9.70649C13.6828 9.31595 14.3159 9.31591 14.7065 9.70641L20 15.0104V5ZM2 3.9934C2 3.44476 2.45531 3 2.9918 3H21.0082C21.556 3 22 3.44495 22 3.9934V20.0066C22 20.5552 21.5447 21 21.0082 21H2.9918C2.44405 21 2 20.5551 2 20.0066V3.9934ZM8 11C6.89543 11 6 10.1046 6 9C6 7.89543 6.89543 7 8 7C9.10457 7 10 7.89543 10 9C10 10.1046 9.10457 11 8 11Z"></path></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 443 B  | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user