Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • hive/imagehoster
1 result
Show changes
Commits on Source (6)
......@@ -12,6 +12,11 @@ RUN apk add \
make \
py-pip
RUN apk add \
--no-cache \
--repository https://dl-3.alpinelinux.org/alpine/edge/testing/ \
vips-dev
# install application dependencies
COPY package.json yarn.lock ./
RUN JOBS=max yarn install --non-interactive --frozen-lockfile
......@@ -31,7 +36,7 @@ WORKDIR /app
RUN apk add \
--no-cache \
--repository https://alpine.global.ssl.fastly.net/alpine/v3.10/community \
fftw
fftw vips
COPY --from=build-stage /app/config config
COPY --from=build-stage /app/lib lib
COPY --from=build-stage /app/node_modules node_modules
......
......@@ -20,6 +20,8 @@ service_url = 'http://localhost:8800'
# default user avatar, should be a png minimum 512x512
default_avatar = 'https://images.hive.blog/DQmb2HNSGKN3pakguJ4ChCRjgkVuDN9WniFRPmrxoJ4sjR4'
# default user cover, should be a png minimum 1344x240
default_cover = 'https://images.ecency.com/DQmdA9wjRyGmDwrTza59yLSjCWMEc9sFD5sC4ZU5kL9UMqo/cover_fallback_day.png'
# log level to output at
log_level = 'debug'
......
/** Serve user cover images. */
import * as config from 'config'
import { base58Enc } from './utils'
import { Account } from '@hiveio/dhive'
import {KoaContext, rpcClient} from './common'
import {APIError} from './error'
const DefaultCover = config.get('default_cover') as string
const sizeW = 1344
const sizeH = 240
export async function coverHandler(ctx: KoaContext) {
ctx.tag({handler: 'cover'})
APIError.assert(ctx.method === 'GET', APIError.Code.InvalidMethod)
APIError.assertParams(ctx.params, ['username'])
const username = ctx.params['username']
interface ExtendedAccount extends Account {
posting_json_metadata?: string
}
const [account]: ExtendedAccount[] = await rpcClient.database.getAccounts([username])
APIError.assert(account, APIError.Code.NoSuchAccount)
let metadata
// read from `posting_json_metadata` if version flag is set
if (account.posting_json_metadata) {
try {
metadata = JSON.parse(account.posting_json_metadata)
if (!metadata.profile || !metadata.profile.version) {
metadata = {}
}
} catch (error) {
ctx.log.debug(error, 'unable to parse json_metadata for %s', account.name)
metadata = {}
}
}
// otherwise, fall back to reading from `json_metadata`
if (!metadata || !metadata.profile) {
try {
metadata = JSON.parse(account.json_metadata)
} catch (error) {
ctx.log.debug(error, 'unable to parse json_metadata for %s', account.name)
metadata = {}
}
}
let coverUrl: string = DefaultCover
if (metadata.profile &&
metadata.profile.cover_image &&
metadata.profile.cover_image.match(/^https?:\/\//)) {
coverUrl = metadata.profile.cover_image
}
ctx.set('Cache-Control', 'public,max-age=600')
ctx.redirect(`/p/${ base58Enc(coverUrl) }?width=${ sizeW }&height=${ sizeH }`)
}
......@@ -242,7 +242,21 @@ export async function proxyHandler(ctx: KoaContext) {
user_agent: 'HiveProxy/1.0 (+https://gitlab.syncad.com/hive/imagehoster)',
} as any)
} catch (cause) {
throw new APIError({cause, code: APIError.Code.UpstreamError})
// old or non existing images, try to get from steemitimages server
try {
ctx.log.debug({url: url.toString()}, 'fetching from steemit server')
res = await fetchUrl(`https://steemitimages.com/0x0/${url.toString()}`, {
open_timeout: 5 * 1000,
response_timeout: 5 * 1000,
read_timeout: 60 * 1000,
compressed: true,
parse_response: false,
follow_max: 5,
user_agent: 'SteemitProxy/1.0 (+https://github.com/steemit/imagehoster)',
} as any)
} catch (cause) {
throw new APIError({cause, code: APIError.Code.UpstreamError})
}
}
APIError.assert(res.bytes <= MAX_IMAGE_SIZE, APIError.Code.PayloadTooLarge)
......
......@@ -3,6 +3,7 @@
import * as Router from 'koa-router'
import {avatarHandler} from './avatar'
import {coverHandler} from './cover'
import {KoaContext} from './common'
import {legacyProxyHandler} from './legacy-proxy'
import {proxyHandler} from './proxy'
......@@ -22,6 +23,7 @@ async function healthcheck(ctx: KoaContext) {
router.get('/', healthcheck as any)
router.get('/.well-known/healthcheck.json', healthcheck as any)
router.get('/u/:username/avatar/:size?', avatarHandler as any)
router.get('/u/:username/cover', coverHandler as any)
router.post('/hs/:accesstoken', uploadHsHandler as any)
router.post('/:username/:signature', uploadHandler as any)
router.post('/cs/:username/:signature', uploadCsHandler as any)
......