Skip to content

Commit

Permalink
Adds model publications
Browse files Browse the repository at this point in the history
  • Loading branch information
jim-toth committed Nov 8, 2023
1 parent e73c39b commit 7e4848b
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 60 deletions.
198 changes: 142 additions & 56 deletions src/publications/authenticated-publications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ import {
VideoPublicationOptions
} from './'

export interface ArFSOpts {
address: string
driveId: string
folderId: string
unixTime: string
}

export interface PublicationResult {
bundleTxId: string
primaryAssetTxId: string
Expand Down Expand Up @@ -52,33 +59,34 @@ export default class AuthenticatedArtByCityPublications {
const { driveId, folderId } = opts.driveId && opts.folderId
? { driveId: opts.driveId, folderId: opts.folderId }
: await this.arfs.getOrCreatePublicationRoot(address)

const arfsOpts = {
address,
driveId,
folderId,
unixTime
}

switch (opts.type) {
case 'image':
return this.publishImage(address, driveId, folderId, unixTime, opts)
return this.createImagePublication(opts, arfsOpts)
case 'audio':
return this.publishAudio(address, driveId, folderId, unixTime, opts)
return this.createAudioPublication(opts, arfsOpts)
case 'model':
return this.createModelPublication(opts, arfsOpts)
case 'video':
case 'text':
default:
throw new Error(`Publication type ${opts.type} is not yet implemented!`)
}
}

private async publishImage(
address: string,
driveId: string,
folderId: string,
unixTime: string,
opts: ImagePublicationOptions
private async createImagePublication(
opts: ImagePublicationOptions,
arfsOpts: ArFSOpts
) {
const publicationItems = await this.createImageDataItems(
opts,
address,
driveId,
folderId,
unixTime,
arfsOpts,
true
)

Expand Down Expand Up @@ -113,10 +121,7 @@ export default class AuthenticatedArtByCityPublications {

private async createImageDataItems(
opts: PublicationOptions,
address: string,
driveId: string,
folderId: string,
unixTime: string,
arfsOpts: ArFSOpts,
isPrimaryPublicationAsset?: boolean
) {
const images = 'images' in opts
Expand All @@ -142,9 +147,9 @@ export default class AuthenticatedArtByCityPublications {
dataContentType: small.type
}),
generateArFSFileTags({
driveId,
parentFolderId: folderId,
unixTime
driveId: arfsOpts.driveId,
parentFolderId: arfsOpts.folderId,
unixTime: arfsOpts.unixTime
})
)

Expand All @@ -164,9 +169,9 @@ export default class AuthenticatedArtByCityPublications {
dataContentType: large.type
}),
generateArFSFileTags({
driveId,
parentFolderId: folderId,
unixTime
driveId: arfsOpts.driveId,
parentFolderId: arfsOpts.folderId,
unixTime: arfsOpts.unixTime
})
)

Expand All @@ -181,7 +186,7 @@ export default class AuthenticatedArtByCityPublications {
...generateAns110Tags(opts),
...generateAtomicLicenseTags(
this.config.contracts.atomicLicense,
JSON.stringify({ owner: address })
JSON.stringify({ owner: arfsOpts.address })
)
)

Expand All @@ -205,9 +210,9 @@ export default class AuthenticatedArtByCityPublications {
description: opts.description
}),
generateArFSFileTags({
driveId,
parentFolderId: folderId,
unixTime
driveId: arfsOpts.driveId,
parentFolderId: arfsOpts.folderId,
unixTime: arfsOpts.unixTime
})
)

Expand All @@ -222,30 +227,18 @@ export default class AuthenticatedArtByCityPublications {
}))
}

private async publishAudio(
address: string,
driveId: string,
folderId: string,
unixTime: string,
opts: AudioPublicationOptions
private async createAudioPublication(
opts: AudioPublicationOptions,
arfsOpts: ArFSOpts
) {
const imageItems = await this.createImageDataItems(
opts,
address,
driveId,
folderId,
unixTime
)
const imageItems = await this.createImageDataItems(opts, arfsOpts)

const {
audioDataItem,
audioMetadataDataItem
} = await this.createAudioDataItems(
opts,
address,
driveId,
folderId,
unixTime,
arfsOpts,
imageItems[0]?.primaryDataItem.id
)

Expand Down Expand Up @@ -281,33 +274,30 @@ export default class AuthenticatedArtByCityPublications {

private async createAudioDataItems(
opts: AudioPublicationOptions,
address: string,
driveId: string,
folderId: string,
unixTime: string,
arfsOpts: ArFSOpts,
thumbnailId?: string
) {
const audioTags: Tag[] = [
const tags: Tag[] = [
new Tag('Content-Type', opts.audio.type),
...generateArtByCityTags(),
...generateAns110Tags(opts),
...generateAtomicLicenseTags(
this.config.contracts.atomicLicense,
JSON.stringify({ owner: address })
JSON.stringify({ owner: arfsOpts.address })
)
]

if (thumbnailId) {
audioTags.push(new Tag('Thumbnail', thumbnailId))
tags.push(new Tag('Thumbnail', thumbnailId))
}

if (opts.slug) {
audioTags.push(new Tag('Slug', opts.slug))
tags.push(new Tag('Slug', opts.slug))
}

const audioDataItem = await this.dataItemFactory.createAndSign(
opts.audio.data,
audioTags
tags
)

const audioMetadataDataItem = await this.dataItemFactory.createAndSign(
Expand All @@ -321,9 +311,9 @@ export default class AuthenticatedArtByCityPublications {
description: opts.description
}),
generateArFSFileTags({
driveId,
parentFolderId: folderId,
unixTime
driveId: arfsOpts.driveId,
parentFolderId: arfsOpts.folderId,
unixTime: arfsOpts.unixTime
})
)

Expand All @@ -333,6 +323,102 @@ export default class AuthenticatedArtByCityPublications {
}
}

private async createModelPublication(
opts: ModelPublicationOptions,
arfsOpts: ArFSOpts
) {
const imageItems = await this.createImageDataItems(opts, arfsOpts)

const {
modelDataItem,
modelMetadataDataItem
} = await this.createModelDataItems(
opts,
arfsOpts,
imageItems[0]?.primaryDataItem.id
)

const dataItems = imageItems.map(({
primaryDataItem,
primaryMetadataDataItem,
smallDataItem,
smallMetadataDataItem,
largeDataItem,
largeMetadataDataItem
}) => {
return [
primaryDataItem,
primaryMetadataDataItem,
smallDataItem,
smallMetadataDataItem,
largeDataItem,
largeMetadataDataItem
]
}).flat()

dataItems.push(modelDataItem, modelMetadataDataItem)

const tx = await this.createPublicationBundleTransaction(dataItems)

return {
bundleTxId: tx.id,
primaryAssetTxId: modelDataItem.id,
primaryMetadataTxId: modelMetadataDataItem.id,
tx
}
}

private async createModelDataItems(
opts: ModelPublicationOptions,
arfsOpts: ArFSOpts,
thumbnailId?: string
) {
const tags: Tag[] = [
new Tag('Content-Type', opts.model.type),
...generateArtByCityTags(),
...generateAns110Tags(opts),
...generateAtomicLicenseTags(
this.config.contracts.atomicLicense,
JSON.stringify({ owner: arfsOpts.address })
)
]

if (thumbnailId) {
tags.push(new Tag('Thumbnail', thumbnailId))
}

if (opts.slug) {
tags.push(new Tag('Slug', opts.slug))
}

const modelDataItem = await this.dataItemFactory.createAndSign(
opts.model.data,
tags
)

const modelMetadataDataItem = await this.dataItemFactory.createAndSign(
JSON.stringify({
name: opts.model.name,
size: opts.model.size,
lastModifiedDate: opts.model.lastModified,
dataTxId: modelDataItem.id,
dataContentType: opts.model.type,
title: opts.title,
description: opts.description
}),
generateArFSFileTags({
driveId: arfsOpts.driveId,
parentFolderId: arfsOpts.folderId,
unixTime: arfsOpts.unixTime
})
)

return {
modelDataItem,
modelMetadataDataItem
}
}

private async createPublicationBundleTransaction(items: DataItem[]) {
const bundle = await bundleAndSignData(items, this.signer)
const tx = await this.arweave.createTransaction({ data: bundle.getRaw() })
Expand Down
10 changes: 9 additions & 1 deletion src/publications/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export interface PublicationImageWithThumbnails {
export interface PublicationAudio extends PublishingFile {
type: AudioMimeTypes
}
export interface PublicationModel extends PublishingFile {
type: ModelMimeTypes
}
export interface BasePublicationOptions {
type: PublicationType
title: string
Expand All @@ -41,12 +44,13 @@ export interface ImagePublicationOptions extends BasePublicationOptions {
images: PublicationImageWithThumbnails[]
}
export interface AudioPublicationOptions extends BasePublicationOptions {
type: 'audio',
type: 'audio'
audio: PublicationAudio
image?: PublicationImageWithThumbnails
}
export interface ModelPublicationOptions extends BasePublicationOptions {
type: 'model'
model: PublicationModel
}
export interface VideoPublicationOptions extends BasePublicationOptions {
type: 'video'
Expand Down Expand Up @@ -78,6 +82,10 @@ export type AudioMimeTypes =
| 'audio/ogg'
| 'audio/webm'

export type ModelMimeTypes =
| 'model/gltf+json'
| 'model/gltf+binary'

export {
default as AuthenticatedArtByCityPublications
} from './authenticated-publications'
Loading

0 comments on commit 7e4848b

Please sign in to comment.