mirror of
https://github.com/aljazceru/landscape-template.git
synced 2025-12-17 22:34:21 +01:00
feat: add image management for stories and user avatar
This commit is contained in:
@@ -88,7 +88,6 @@ export interface NexusGenScalars {
|
|||||||
|
|
||||||
export interface NexusGenObjects {
|
export interface NexusGenObjects {
|
||||||
Author: { // root type
|
Author: { // root type
|
||||||
avatar: string; // String!
|
|
||||||
id: number; // Int!
|
id: number; // Int!
|
||||||
join_date: NexusGenScalars['Date']; // Date!
|
join_date: NexusGenScalars['Date']; // Date!
|
||||||
lightning_address?: string | null; // String
|
lightning_address?: string | null; // String
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const {
|
|||||||
nonNull,
|
nonNull,
|
||||||
} = require('nexus');
|
} = require('nexus');
|
||||||
const { prisma } = require('../../../prisma');
|
const { prisma } = require('../../../prisma');
|
||||||
const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl');
|
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||||
|
|
||||||
|
|
||||||
const Category = objectType({
|
const Category = objectType({
|
||||||
@@ -15,6 +15,7 @@ const Category = objectType({
|
|||||||
t.nonNull.string('title');
|
t.nonNull.string('title');
|
||||||
t.string('cover_image', {
|
t.string('cover_image', {
|
||||||
async resolve(parent) {
|
async resolve(parent) {
|
||||||
|
if (!parent.cover_image_id) return null
|
||||||
const imgObject = await prisma.hostedImage.findUnique({
|
const imgObject = await prisma.hostedImage.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: parent.cover_image_id
|
id: parent.cover_image_id
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const {
|
|||||||
nonNull,
|
nonNull,
|
||||||
} = require('nexus');
|
} = require('nexus');
|
||||||
const { prisma } = require('../../../prisma');
|
const { prisma } = require('../../../prisma');
|
||||||
const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl');
|
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@ const Hackathon = objectType({
|
|||||||
t.nonNull.string('description');
|
t.nonNull.string('description');
|
||||||
t.nonNull.string('cover_image', {
|
t.nonNull.string('cover_image', {
|
||||||
async resolve(parent) {
|
async resolve(parent) {
|
||||||
|
if (!parent.cover_image_id) return null
|
||||||
const imgObject = await prisma.hostedImage.findUnique({
|
const imgObject = await prisma.hostedImage.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: parent.cover_image_id
|
id: parent.cover_image_id
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ const { prisma } = require('../../../prisma');
|
|||||||
const { getUserByPubKey } = require('../../../auth/utils/helperFuncs');
|
const { getUserByPubKey } = require('../../../auth/utils/helperFuncs');
|
||||||
const { ApolloError } = require('apollo-server-lambda');
|
const { ApolloError } = require('apollo-server-lambda');
|
||||||
const { marked } = require('marked');
|
const { marked } = require('marked');
|
||||||
const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl');
|
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||||
const { ImageInput } = require('./misc');
|
const { ImageInput } = require('./misc');
|
||||||
|
const { deleteImage } = require('../../../services/imageUpload.service');
|
||||||
|
|
||||||
|
|
||||||
const POST_TYPE = enumType({
|
const POST_TYPE = enumType({
|
||||||
@@ -39,7 +40,17 @@ const Author = objectType({
|
|||||||
definition(t) {
|
definition(t) {
|
||||||
t.nonNull.int('id');
|
t.nonNull.int('id');
|
||||||
t.nonNull.string('name');
|
t.nonNull.string('name');
|
||||||
t.nonNull.string('avatar');
|
t.nonNull.string('avatar', {
|
||||||
|
async resolve(parent) {
|
||||||
|
const imgObject = await prisma.hostedImage.findUnique({
|
||||||
|
where: {
|
||||||
|
id: parent.avatar_id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return resolveImgObjectToUrl(imgObject);
|
||||||
|
}
|
||||||
|
});
|
||||||
t.nonNull.date('join_date');
|
t.nonNull.date('join_date');
|
||||||
|
|
||||||
t.string('lightning_address');
|
t.string('lightning_address');
|
||||||
@@ -75,6 +86,7 @@ const Story = objectType({
|
|||||||
});
|
});
|
||||||
t.string('cover_image', {
|
t.string('cover_image', {
|
||||||
async resolve(parent) {
|
async resolve(parent) {
|
||||||
|
if (!parent.cover_image_id) return null
|
||||||
const imgObject = await prisma.hostedImage.findUnique({
|
const imgObject = await prisma.hostedImage.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: parent.cover_image_id
|
id: parent.cover_image_id
|
||||||
@@ -153,6 +165,7 @@ const Bounty = objectType({
|
|||||||
});
|
});
|
||||||
t.string('cover_image', {
|
t.string('cover_image', {
|
||||||
async resolve(parent) {
|
async resolve(parent) {
|
||||||
|
if (!parent.cover_image_id) return null
|
||||||
const imgObject = await prisma.hostedImage.findUnique({
|
const imgObject = await prisma.hostedImage.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: parent.cover_image_id
|
id: parent.cover_image_id
|
||||||
@@ -366,6 +379,64 @@ const getPostById = extendType({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const addCoverImage = async (providerImageId) => {
|
||||||
|
const newCoverImage = await prisma.hostedImage.findFirst({
|
||||||
|
where: {
|
||||||
|
provider_image_id: providerImageId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!newCoverImage) throw new ApolloError("New cover image not found")
|
||||||
|
|
||||||
|
await prisma.hostedImage.update({
|
||||||
|
where: {
|
||||||
|
id: newCoverImage.id
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
is_used: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return newCoverImage
|
||||||
|
}
|
||||||
|
|
||||||
|
const getHostedImageIdsFromBody = async (body, oldBodyImagesIds = null) => {
|
||||||
|
let bodyImageIds = []
|
||||||
|
|
||||||
|
const regex = /(?:!\[(.*?)\]\((.*?)\))/g
|
||||||
|
let match;
|
||||||
|
while((match = regex.exec(body))) {
|
||||||
|
const [,,value] = match
|
||||||
|
|
||||||
|
// Useful for old external images in case of duplicates. We need to be sure we are targeting an image from the good story.
|
||||||
|
const where = oldBodyImagesIds ? {
|
||||||
|
AND: [
|
||||||
|
{ url: value },
|
||||||
|
{ id: { in: oldBodyImagesIds } }
|
||||||
|
]
|
||||||
|
} :
|
||||||
|
{
|
||||||
|
url: value,
|
||||||
|
}
|
||||||
|
|
||||||
|
const hostedImage = await prisma.hostedImage.findFirst({
|
||||||
|
where
|
||||||
|
})
|
||||||
|
if (hostedImage) {
|
||||||
|
bodyImageIds.push(hostedImage.id)
|
||||||
|
await prisma.hostedImage.update({
|
||||||
|
where: {
|
||||||
|
id: hostedImage.id
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
is_used: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bodyImageIds
|
||||||
|
}
|
||||||
|
|
||||||
const createStory = extendType({
|
const createStory = extendType({
|
||||||
type: 'Mutation',
|
type: 'Mutation',
|
||||||
definition(t) {
|
definition(t) {
|
||||||
@@ -382,20 +453,64 @@ const createStory = extendType({
|
|||||||
|
|
||||||
let was_published = false;
|
let was_published = false;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: validate post data
|
||||||
|
|
||||||
|
let coverImage = null
|
||||||
|
let bodyImageIds = []
|
||||||
|
|
||||||
|
// Edit story
|
||||||
if (id) {
|
if (id) {
|
||||||
const oldPost = await prisma.story.findFirst({
|
const oldPost = await prisma.story.findFirst({
|
||||||
where: { id },
|
where: { id },
|
||||||
select: {
|
select: {
|
||||||
user_id: true,
|
user_id: true,
|
||||||
is_published: true
|
is_published: true,
|
||||||
|
cover_image_id: true,
|
||||||
|
body_image_ids: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
was_published = oldPost.is_published;
|
was_published = oldPost.is_published;
|
||||||
if (user.id !== oldPost.user_id)
|
if (user.id !== oldPost.user_id) throw new ApolloError("Not post author")
|
||||||
throw new ApolloError("Not post author")
|
|
||||||
}
|
|
||||||
// TODO: validate post data
|
|
||||||
|
|
||||||
|
// Body images
|
||||||
|
bodyImageIds = await getHostedImageIdsFromBody(body, oldPost.body_image_ids)
|
||||||
|
|
||||||
|
// Old cover image is found
|
||||||
|
if (oldPost.cover_image_id) {
|
||||||
|
const oldCoverImage = await prisma.hostedImage.findFirst({
|
||||||
|
where : {
|
||||||
|
id: oldPost.cover_image_id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// New cover image
|
||||||
|
if (cover_image?.id && cover_image.id !== oldCoverImage?.provider_image_id) {
|
||||||
|
await deleteImage(oldCoverImage.id)
|
||||||
|
coverImage = await addCoverImage(cover_image.id)
|
||||||
|
} else {
|
||||||
|
coverImage = oldCoverImage
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No old image found and new cover image
|
||||||
|
if (cover_image?.id) {
|
||||||
|
coverImage = await addCoverImage(cover_image.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove unused body images
|
||||||
|
const unusedImagesIds = oldPost.body_image_ids.filter(x => !bodyImageIds.includes(x));
|
||||||
|
unusedImagesIds.map(async i => await deleteImage(i))
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Body images
|
||||||
|
bodyImageIds = await getHostedImageIdsFromBody(body)
|
||||||
|
|
||||||
|
// New story and new cover image
|
||||||
|
if (cover_image?.id) {
|
||||||
|
coverImage = await addCoverImage(cover_image.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Preprocess & insert
|
// Preprocess & insert
|
||||||
const htmlBody = marked.parse(body);
|
const htmlBody = marked.parse(body);
|
||||||
@@ -408,12 +523,14 @@ const createStory = extendType({
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
// ----------------
|
const coverImageRel = coverImage ? {
|
||||||
// Check the uploaded cover image & the images in the body,
|
cover_image_rel: {
|
||||||
// remove the old one from the hosting service, then replace it with these ones
|
connect:
|
||||||
// ----------------
|
{
|
||||||
|
id: coverImage ? coverImage.id : null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} : {}
|
||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
await prisma.story.update({
|
await prisma.story.update({
|
||||||
@@ -430,7 +547,7 @@ const createStory = extendType({
|
|||||||
data: {
|
data: {
|
||||||
title,
|
title,
|
||||||
body,
|
body,
|
||||||
cover_image: cover_image.url,
|
cover_image: '',
|
||||||
excerpt,
|
excerpt,
|
||||||
is_published: was_published || is_published,
|
is_published: was_published || is_published,
|
||||||
tags: {
|
tags: {
|
||||||
@@ -447,16 +564,17 @@ const createStory = extendType({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
body_image_ids: bodyImageIds,
|
||||||
|
...coverImageRel
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return await prisma.story.create({
|
||||||
return prisma.story.create({
|
|
||||||
data: {
|
data: {
|
||||||
title,
|
title,
|
||||||
body,
|
body,
|
||||||
cover_image: cover_image.url,
|
cover_image: '',
|
||||||
excerpt,
|
excerpt,
|
||||||
is_published,
|
is_published,
|
||||||
tags: {
|
tags: {
|
||||||
@@ -477,7 +595,9 @@ const createStory = extendType({
|
|||||||
connect: {
|
connect: {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
body_image_ids: bodyImageIds,
|
||||||
|
...coverImageRel
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -502,17 +622,39 @@ const deleteStory = extendType({
|
|||||||
const oldPost = await prisma.story.findFirst({
|
const oldPost = await prisma.story.findFirst({
|
||||||
where: { id },
|
where: { id },
|
||||||
select: {
|
select: {
|
||||||
user_id: true
|
user_id: true,
|
||||||
|
body_image_ids: true,
|
||||||
|
cover_image_id: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (user.id !== oldPost.user_id)
|
if (user.id !== oldPost.user_id)
|
||||||
throw new ApolloError("Not post author")
|
throw new ApolloError("Not post author")
|
||||||
|
|
||||||
return prisma.story.delete({
|
const deletedPost = await prisma.story.delete({
|
||||||
where: {
|
where: {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const coverImage = await prisma.hostedImage.findMany({
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ id: oldPost.cover_image_id },
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
in: oldPost.body_image_ids
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
provider_image_id: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
coverImage.map(async i => await deleteImage(i.id))
|
||||||
|
|
||||||
|
return deletedPost
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const {
|
|||||||
nonNull,
|
nonNull,
|
||||||
} = require('nexus')
|
} = require('nexus')
|
||||||
const { prisma } = require('../../../prisma');
|
const { prisma } = require('../../../prisma');
|
||||||
const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl');
|
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||||
|
|
||||||
const { paginationArgs, getLnurlDetails, lightningAddressToLnurl } = require('./helpers');
|
const { paginationArgs, getLnurlDetails, lightningAddressToLnurl } = require('./helpers');
|
||||||
const { MakerRole } = require('./users');
|
const { MakerRole } = require('./users');
|
||||||
@@ -20,6 +20,7 @@ const Project = objectType({
|
|||||||
t.nonNull.string('description');
|
t.nonNull.string('description');
|
||||||
t.nonNull.string('cover_image', {
|
t.nonNull.string('cover_image', {
|
||||||
async resolve(parent) {
|
async resolve(parent) {
|
||||||
|
if (!parent.cover_image_id) return null
|
||||||
const imgObject = await prisma.hostedImage.findUnique({
|
const imgObject = await prisma.hostedImage.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: parent.cover_image_id
|
id: parent.cover_image_id
|
||||||
@@ -31,6 +32,7 @@ const Project = objectType({
|
|||||||
});
|
});
|
||||||
t.nonNull.string('thumbnail_image', {
|
t.nonNull.string('thumbnail_image', {
|
||||||
async resolve(parent) {
|
async resolve(parent) {
|
||||||
|
if (!parent.thumbnail_image_id) return null
|
||||||
const imgObject = await prisma.hostedImage.findUnique({
|
const imgObject = await prisma.hostedImage.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: parent.thumbnail_image_id
|
id: parent.thumbnail_image_id
|
||||||
@@ -42,6 +44,7 @@ const Project = objectType({
|
|||||||
});
|
});
|
||||||
t.nonNull.list.nonNull.string('screenshots', {
|
t.nonNull.list.nonNull.string('screenshots', {
|
||||||
async resolve(parent) {
|
async resolve(parent) {
|
||||||
|
if (!parent.screenshots_ids) return null
|
||||||
const imgObject = await prisma.hostedImage.findMany({
|
const imgObject = await prisma.hostedImage.findMany({
|
||||||
where: {
|
where: {
|
||||||
id: { in: parent.screenshots_ids }
|
id: { in: parent.screenshots_ids }
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const {
|
|||||||
nonNull,
|
nonNull,
|
||||||
} = require('nexus');
|
} = require('nexus');
|
||||||
const { prisma } = require('../../../prisma');
|
const { prisma } = require('../../../prisma');
|
||||||
|
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ const Tournament = objectType({
|
|||||||
t.nonNull.string('thumbnail_image');
|
t.nonNull.string('thumbnail_image');
|
||||||
t.nonNull.string('cover_image', {
|
t.nonNull.string('cover_image', {
|
||||||
async resolve(parent) {
|
async resolve(parent) {
|
||||||
|
if (!parent.cover_image_id) return null
|
||||||
const imgObject = await prisma.hostedImage.findUnique({
|
const imgObject = await prisma.hostedImage.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: parent.cover_image_id
|
id: parent.cover_image_id
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const { getUserByPubKey } = require("../../../auth/utils/helperFuncs");
|
|||||||
const { removeNulls } = require("./helpers");
|
const { removeNulls } = require("./helpers");
|
||||||
const { ImageInput } = require('./misc');
|
const { ImageInput } = require('./misc');
|
||||||
const { Tournament } = require('./tournaments');
|
const { Tournament } = require('./tournaments');
|
||||||
const resolveImgObjectToUrl = require('../../../utils/resolveImageUrl');
|
const { resolveImgObjectToUrl } = require('../../../utils/resolveImageUrl');
|
||||||
const { deleteImage } = require('../../../services/imageUpload.service');
|
const { deleteImage } = require('../../../services/imageUpload.service');
|
||||||
|
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@ const BaseUser = interfaceType({
|
|||||||
t.nonNull.string('name');
|
t.nonNull.string('name');
|
||||||
t.nonNull.string('avatar', {
|
t.nonNull.string('avatar', {
|
||||||
async resolve(parent) {
|
async resolve(parent) {
|
||||||
|
if (!parent.avatar_id) return null
|
||||||
const imgObject = await prisma.hostedImage.findUnique({
|
const imgObject = await prisma.hostedImage.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: parent.avatar_id
|
id: parent.avatar_id
|
||||||
@@ -301,15 +302,6 @@ const updateProfileDetails = extendType({
|
|||||||
if (newAvatar && newAvatar.id !== user.avatar_id) {
|
if (newAvatar && newAvatar.id !== user.avatar_id) {
|
||||||
avatarId = newAvatar.id;
|
avatarId = newAvatar.id;
|
||||||
|
|
||||||
// Set is_used to false in case of deleteImage() fail. The scheduled job will try to delete the HostedImage row
|
|
||||||
await prisma.hostedImage.update({
|
|
||||||
where: {
|
|
||||||
id: user.avatar_id
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
is_used: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await prisma.hostedImage.update({
|
await prisma.hostedImage.update({
|
||||||
where: {
|
where: {
|
||||||
id: newAvatar.id
|
id: newAvatar.id
|
||||||
@@ -319,7 +311,7 @@ const updateProfileDetails = extendType({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
deleteImage(user.avatar_id)
|
await deleteImage(user.avatar_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,11 +85,21 @@ const loginHandler = async (req, res) => {
|
|||||||
const nostr_prv_key = generatePrivateKey();
|
const nostr_prv_key = generatePrivateKey();
|
||||||
const nostr_pub_key = getPublicKey(nostr_prv_key);
|
const nostr_pub_key = getPublicKey(nostr_prv_key);
|
||||||
|
|
||||||
|
const avatar = await prisma.hostedImage.create({
|
||||||
|
data: {
|
||||||
|
filename: 'avatar.svg',
|
||||||
|
provider: 'external',
|
||||||
|
is_used: true,
|
||||||
|
url: `https://avatars.dicebear.com/api/bottts/${key}.svg`,
|
||||||
|
provider_image_id: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const createdUser = await prisma.user.create({
|
const createdUser = await prisma.user.create({
|
||||||
data: {
|
data: {
|
||||||
pubKey: key,
|
pubKey: key,
|
||||||
name: key,
|
name: key,
|
||||||
avatar: `https://avatars.dicebear.com/api/bottts/${key}.svg`,
|
avatar_id: avatar.id,
|
||||||
nostr_prv_key,
|
nostr_prv_key,
|
||||||
nostr_pub_key,
|
nostr_pub_key,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const extractKeyFromCookie = require('../../utils/extractKeyFromCookie')
|
|||||||
const { getUserByPubKey } = require('../../auth/utils/helperFuncs')
|
const { getUserByPubKey } = require('../../auth/utils/helperFuncs')
|
||||||
const { getDirectUploadUrl } = require('../../services/imageUpload.service')
|
const { getDirectUploadUrl } = require('../../services/imageUpload.service')
|
||||||
const { prisma } = require('../../prisma')
|
const { prisma } = require('../../prisma')
|
||||||
|
const { getUrlFromProvider } = require('../../utils/resolveImageUrl')
|
||||||
|
|
||||||
const postUploadImageUrl = async (req, res) => {
|
const postUploadImageUrl = async (req, res) => {
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ const postUploadImageUrl = async (req, res) => {
|
|||||||
const hostedImage = await prisma.hostedImage.create({
|
const hostedImage = await prisma.hostedImage.create({
|
||||||
data: {
|
data: {
|
||||||
filename,
|
filename,
|
||||||
url: uploadUrl.uploadURL,
|
url: getUrlFromProvider(uploadUrl.provider, uploadUrl.id),
|
||||||
provider_image_id: uploadUrl.id,
|
provider_image_id: uploadUrl.id,
|
||||||
provider: uploadUrl.provider
|
provider: uploadUrl.provider
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -42,6 +42,19 @@ async function getDirectUploadUrl() {
|
|||||||
return { id: data.id, uploadURL: data.uploadURL, provider: 'cloudflare' }
|
return { id: data.id, uploadURL: data.uploadURL, provider: 'cloudflare' }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function deleteImageFromProvider(providerImageId) {
|
||||||
|
try {
|
||||||
|
const url = operationUrls['image.delete'] + providerImageId
|
||||||
|
const result = await axios.delete(url, getAxiosConfig())
|
||||||
|
|
||||||
|
if (!result.data.success) {
|
||||||
|
throw new Error(result.data, { cause: result.data.errors })
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function deleteImage(hostedImageId) {
|
async function deleteImage(hostedImageId) {
|
||||||
if (!hostedImageId) throw new Error("argument 'hostedImageId' must be provider")
|
if (!hostedImageId) throw new Error("argument 'hostedImageId' must be provider")
|
||||||
|
|
||||||
@@ -52,23 +65,34 @@ async function deleteImage(hostedImageId) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!hostedImage) throw new Error(`No HostedImage row found for HostedImage.id=${hostedImageId}`)
|
if (!hostedImage) throw new Error(`No HostedImage row found for HostedImage.id=${hostedImageId}`)
|
||||||
if (hostedImage.provider_image_id && hostedImage.provider_image_id === '') throw new Error(`Field 'provider_image_id' for HostedImage.id=${hostedImageId} must not be empty. Current value '${hostedImage.provider_image_id}'`)
|
if (hostedImage.provider_image_id && hostedImage.provider_image_id === '')
|
||||||
|
throw new Error(`Field 'provider_image_id' for HostedImage.id=${hostedImageId} must not be empty. Current value '${hostedImage.provider_image_id}'`)
|
||||||
|
|
||||||
const url = operationUrls['image.delete'] + hostedImage.provider_image_id
|
// Set is_used to false in case of deletion fail from the hosting image provider. The scheduled job will try to delete the HostedImage row
|
||||||
const result = await axios.delete(url, getAxiosConfig())
|
await prisma.hostedImage.update({
|
||||||
|
|
||||||
if (!result.data.success) {
|
|
||||||
throw new Error(result.data, { cause: result.data.errors })
|
|
||||||
}
|
|
||||||
|
|
||||||
await prisma.hostedImage.delete({
|
|
||||||
where: {
|
where: {
|
||||||
id: hostedImageId,
|
id: hostedImage.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
is_used: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (hostedImage.provider_image_id && hostedImage.provider_image_id !== '') {
|
||||||
|
deleteImageFromProvider(hostedImage.provider_image_id)
|
||||||
|
.then(async () => {
|
||||||
|
await prisma.hostedImage.delete({
|
||||||
|
where: {
|
||||||
|
id: hostedImageId,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((error) => console.error(error))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getDirectUploadUrl,
|
getDirectUploadUrl,
|
||||||
deleteImage,
|
deleteImage,
|
||||||
|
deleteImageFromProvider,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,16 +26,20 @@ function resolveImgObjectToUrl(imgObject, variant = null) {
|
|||||||
return imgObject.url
|
return imgObject.url
|
||||||
}
|
}
|
||||||
|
|
||||||
const provider = PROVIDERS.find((p) => p.name === imgObject.provider)
|
return getUrlFromProvider(imgObject.provider, imgObject.provider_image_id, variant)
|
||||||
|
}
|
||||||
|
|
||||||
if (provider) {
|
function getUrlFromProvider(provider, providerImageId, variant = null) {
|
||||||
if (provider && provider.name === 'cloudflare') {
|
const p = PROVIDERS.find((p) => p.name === provider)
|
||||||
const variantName = variant ?? provider.variants.find((v) => v.default).name
|
|
||||||
return provider.prefixUrl + imgObject.provider_image_id + '/' + variantName
|
if (p) {
|
||||||
|
if (p && p.name === 'cloudflare') {
|
||||||
|
const variantName = variant ?? p.variants.find((v) => v.default).name
|
||||||
|
return p.prefixUrl + providerImageId + '/' + variantName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('Hosting images provider not supported')
|
throw new Error('Hosting images provider not supported')
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = resolveImgObjectToUrl
|
module.exports = { resolveImgObjectToUrl, getUrlFromProvider }
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ ADD COLUMN "screenshots_ids" INTEGER[],
|
|||||||
ADD COLUMN "thumbnail_image_id" INTEGER;
|
ADD COLUMN "thumbnail_image_id" INTEGER;
|
||||||
|
|
||||||
-- AlterTable
|
-- AlterTable
|
||||||
ALTER TABLE "Story" ADD COLUMN "cover_image_id" INTEGER;
|
ALTER TABLE "Story" ADD COLUMN "body_image_ids" INTEGER[],
|
||||||
|
ADD COLUMN "cover_image_id" INTEGER;
|
||||||
|
|
||||||
-- AlterTable
|
-- AlterTable
|
||||||
ALTER TABLE "User" ADD COLUMN "avatar_id" INTEGER;
|
ALTER TABLE "User" ADD COLUMN "avatar_id" INTEGER;
|
||||||
@@ -185,6 +185,7 @@ model Story {
|
|||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
body String
|
body String
|
||||||
|
body_image_ids Int[]
|
||||||
excerpt String
|
excerpt String
|
||||||
cover_image String?
|
cover_image String?
|
||||||
cover_image_id Int?
|
cover_image_id Int?
|
||||||
|
|||||||
@@ -180,9 +180,30 @@ async function migrateOldImages() {
|
|||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
cover_image: true,
|
cover_image: true,
|
||||||
|
body: true,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
for (const story of stories) {
|
for (const story of stories) {
|
||||||
|
/**
|
||||||
|
* Story.body to Story.body_image_ids
|
||||||
|
**/
|
||||||
|
let bodyImageIds = [];
|
||||||
|
const regex = /(?:!\[(.*?)\]\((.*?)\))/g
|
||||||
|
let match;
|
||||||
|
while((match = regex.exec(story.body))) {
|
||||||
|
const [,,value] = match
|
||||||
|
let hostedImageId = await _insertInHostedImage(value)
|
||||||
|
bodyImageIds.push(hostedImageId)
|
||||||
|
}
|
||||||
|
if (bodyImageIds.length > 0) {
|
||||||
|
await _updateObjectWithHostedImageId(prisma.story, story.id, {
|
||||||
|
body_image_ids: bodyImageIds,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Story.cover_image to Story.cover_image_id
|
||||||
|
**/
|
||||||
if (story.cover_image) {
|
if (story.cover_image) {
|
||||||
let hostedImageId = await _insertInHostedImage(story.cover_image)
|
let hostedImageId = await _insertInHostedImage(story.cover_image)
|
||||||
await _updateObjectWithHostedImageId(prisma.story, story.id, {
|
await _updateObjectWithHostedImageId(prisma.story, story.id, {
|
||||||
|
|||||||
Reference in New Issue
Block a user