Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Part of NDLA common
* Copyright (C) 2026 NDLA
*
* See LICENSE
*
*/

package no.ndla.common.model.domain

import enumeratum.*
import no.ndla.common.errors.ValidationException
import sttp.tapir.Codec.PlainCodec
import sttp.tapir.Schema
import sttp.tapir.codec.enumeratum.*

import scala.util.{Failure, Success, Try}

sealed abstract class AiGenerated(override val entryName: String) extends EnumEntry

object AiGenerated extends Enum[AiGenerated] with CirceEnum[AiGenerated] {
case object Partial extends AiGenerated("partial")
case object Yes extends AiGenerated("yes")
case object No extends AiGenerated("no")

val values: IndexedSeq[AiGenerated] = findValues

def all: Seq[String] = AiGenerated.values.map(_.entryName)
def valueOf(s: String): Option[AiGenerated] = AiGenerated.withNameOption(s)

def valueOfOrError(s: String): Try[AiGenerated] = valueOf(s) match {
case Some(p) => Success(p)
case None =>
val validGeneratedValues = values.map(_.toString).mkString(", ")
Failure(ValidationException("aiGenerated", s"'$s' is not a valid priority. Must be one of $validGeneratedValues"))
}

implicit def schema: Schema[AiGenerated] = schemaForEnumEntry[AiGenerated]
implicit def codec: PlainCodec[AiGenerated] = plainCodecEnumEntry[AiGenerated]
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Denne må bytte navn til V27

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
update imagemetadata
set metadata = jsonb_set(metadata, '{aiGenerated}', '"no"'::jsonb)
where metadata->>'aiGenerated' is null
and metadata is not null;
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.{Decoder, Encoder}
import no.ndla.common.model.NDLADate
import no.ndla.common.model.api.CopyrightDTO
import no.ndla.common.model.domain.AiGenerated
import sttp.tapir.Schema.annotations.description

@description("Meta information for the image")
Expand Down Expand Up @@ -44,6 +45,8 @@ case class ImageMetaInformationV3DTO(
image: ImageFileDTO,
@description("Describes if the image is inactive or not")
inactive: Boolean,
@description("Describes whether the image is AI generated")
aiGenerated: AiGenerated,
)

object ImageMetaInformationV3DTO {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package no.ndla.imageapi.model.api
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.{Decoder, Encoder}
import no.ndla.common.model.api.CopyrightDTO
import no.ndla.common.model.domain.AiGenerated
import sttp.tapir.Schema.annotations.description

// format: off
Expand All @@ -22,7 +23,8 @@ case class NewImageMetaInformationV2DTO(
@description("Searchable tags for the image") tags: Seq[String],
@description("Caption for the image") caption: String,
@description("ISO 639-1 code that represents the language used in the caption") language: String,
@description("Describes if the model has released use of the image, allowed values are 'not-set', 'yes', 'no', and 'not-applicable', defaults to 'no'") modelReleased: Option[String]
@description("Describes if the model has released use of the image, allowed values are 'not-set', 'yes', 'no', and 'not-applicable', defaults to 'no'") modelReleased: Option[String],
@description("Describes whether the image is AI generated") aiGenerated: AiGenerated,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Her må vi ha ed klar med denne funksjonaliteten ellers vil det ikkje funere å opprette nye bilder siden denne ikkje er optional. Men ser jo at dei ber om det.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tipper dette krever fem minutter med arbeid i ED, så tror ikke det har allverdens å si.

)

object NewImageMetaInformationV2DTO{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package no.ndla.imageapi.model.api
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.{Decoder, Encoder}
import no.ndla.common.model.api.{CopyrightDTO, UpdateOrDelete}
import no.ndla.common.model.domain.AiGenerated
import sttp.tapir.Schema.annotations.description

@description("Meta information for the image")
Expand All @@ -31,6 +32,8 @@ case class UpdateImageMetaInformationDTO(
modelReleased: Option[String],
@description("Whether the image is inactive")
inactive: Option[Boolean],
@description("Describes whether the image is AI generated")
aiGenerated: Option[AiGenerated],
)

object UpdateImageMetaInformationDTO {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import no.ndla.common.CirceUtil
import no.ndla.common.model.NDLADate
import no.ndla.common.model.domain.Tag
import no.ndla.common.model.domain.{AiGenerated, Tag}
import no.ndla.common.model.domain.article.Copyright
import no.ndla.imageapi.Props
import scalikejdbc.*
Expand All @@ -34,6 +34,7 @@ case class ImageMetaInformation(
modelReleased: ModelReleasedStatus.Value,
editorNotes: Seq[EditorNote],
inactive: Boolean,
aiGenerated: AiGenerated,
)

object ImageMetaInformation {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class ConverterService(using clock: Clock, props: Props) extends StrictLogging {
editorNotes = editorNotes,
image = apiImageFile,
inactive = imageMeta.inactive,
aiGenerated = imageMeta.aiGenerated,
)
)
})
Expand Down Expand Up @@ -279,6 +280,7 @@ class ConverterService(using clock: Clock, props: Props) extends StrictLogging {
modelReleased = modelStatus,
editorNotes = Seq(domain.EditorNote(now, user.id, "Image created.")),
inactive = false,
aiGenerated = imageMeta.aiGenerated,
)
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class ImageIndexService(using
textField("editorNotes"),
keywordField("podcastFriendly"),
keywordField("users"),
keywordField("aiGenerated"),
nestedField("imageFiles").fields(
intField("imageSize"),
textField("previewUrl"),
Expand Down
10 changes: 9 additions & 1 deletion image-api/src/test/scala/no/ndla/imageapi/TestData.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ package no.ndla.imageapi
import no.ndla.common.aws.NdlaS3Object
import no.ndla.common.model.{NDLADate, api as commonApi}
import no.ndla.common.model.domain.article.Copyright
import no.ndla.common.model.domain.{Author, ContributorType, Tag, UploadedFile}
import no.ndla.common.model.domain.{AiGenerated, Author, ContributorType, Tag, UploadedFile}
import no.ndla.imageapi.model.api
import no.ndla.imageapi.model.api.ImageMetaInformationV2DTO
import no.ndla.imageapi.model.domain.*
Expand Down Expand Up @@ -59,6 +59,7 @@ class TestData(using imageConverter: ImageConverter) {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

val apiElg: ImageMetaInformationV2DTO = api.ImageMetaInformationV2DTO(
Expand Down Expand Up @@ -159,6 +160,7 @@ class TestData(using imageConverter: ImageConverter) {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

val jerv: ImageMetaInformation = new ImageMetaInformation(
Expand Down Expand Up @@ -195,6 +197,7 @@ class TestData(using imageConverter: ImageConverter) {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

val mink = new ImageMetaInformation(
Expand Down Expand Up @@ -231,6 +234,7 @@ class TestData(using imageConverter: ImageConverter) {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

val rein = new ImageMetaInformation(
Expand Down Expand Up @@ -267,6 +271,7 @@ class TestData(using imageConverter: ImageConverter) {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

val nonexisting: ImageMetaInformation = new ImageMetaInformation(
Expand Down Expand Up @@ -303,6 +308,7 @@ class TestData(using imageConverter: ImageConverter) {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

val nonexistingWithoutThumb = new ImageMetaInformation(
Expand Down Expand Up @@ -339,6 +345,7 @@ class TestData(using imageConverter: ImageConverter) {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

val testdata: List[ImageMetaInformation] = List(elg, bjorn, jerv, mink, rein)
Expand Down Expand Up @@ -423,6 +430,7 @@ class TestData(using imageConverter: ImageConverter) {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)
def clownfishS3Object: NdlaS3Object = mockS3ObjectFromDisk("clownfish.jpg", ImageContentType.Jpeg)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ package no.ndla.imageapi.controller
import no.ndla.common.Clock
import no.ndla.common.model.NDLADate
import no.ndla.network.tapir.{ErrorHandling, ErrorHelpers, Routes, TapirController}
import no.ndla.common.model.domain.{Author, ContributorType}
import no.ndla.common.model.domain.{AiGenerated, Author, ContributorType}
import no.ndla.common.model.domain.article.Copyright
import no.ndla.imageapi.model.domain.{
ImageAltText,
Expand Down Expand Up @@ -70,6 +70,7 @@ class HealthControllerTest extends UnitSuite with TestEnvironment with TapirCont
ModelReleasedStatus.NOT_APPLICABLE,
Seq.empty,
false,
AiGenerated.No,
)

test("that /health/readiness returns 200 on success") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ package no.ndla.imageapi.controller

import no.ndla.common.{CirceUtil, Clock}
import no.ndla.common.model.NDLADate
import no.ndla.common.model.domain.Tag
import no.ndla.common.model.domain.{AiGenerated, Tag}
import no.ndla.common.model.domain.article.Copyright
import no.ndla.imageapi.model.api.{
ImageMetaSummaryDTO,
Expand Down Expand Up @@ -85,7 +85,8 @@ class ImageControllerV2Test extends UnitSuite with TestEnvironment with TapirCon
| "lel"
| ],
| "caption": "captionheredude",
| "language": "no"
| "language": "no",
| "aiGenerated": "no"
|}
""".stripMargin

Expand Down Expand Up @@ -260,6 +261,7 @@ class ImageControllerV2Test extends UnitSuite with TestEnvironment with TapirCon
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

when(writeService.storeNewImage(any[NewImageMetaInformationV2DTO], any, any)).thenReturn(Success(sampleImageMeta))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

package no.ndla.imageapi.controller

import no.ndla.common.model.domain.AiGenerated
import no.ndla.common.{CirceUtil, Clock}
import no.ndla.common.model.domain.article.Copyright
import no.ndla.common.model.{NDLADate, api as commonApi}
Expand Down Expand Up @@ -91,6 +92,7 @@ class InternControllerTest extends UnitSuite with TestEnvironment with TapirCont
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.Yes,
)

override def beforeEach(): Unit = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package no.ndla.imageapi.service

import no.ndla.common.model.NDLADate
import no.ndla.common.model.domain.AiGenerated
import no.ndla.common.model.domain.article.Copyright
import no.ndla.imageapi.model.domain.*
import no.ndla.imageapi.{TestEnvironment, UnitSuite}
Expand Down Expand Up @@ -41,6 +42,7 @@ class ConverterServiceTest extends UnitSuite with TestEnvironment {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

val WantingImageMetaInformation = new ImageMetaInformation(
Expand All @@ -58,6 +60,7 @@ class ConverterServiceTest extends UnitSuite with TestEnvironment {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

val MultiLangImage = new ImageMetaInformation(
Expand All @@ -75,6 +78,7 @@ class ConverterServiceTest extends UnitSuite with TestEnvironment {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

test("That asApiImageMetaInformationWithDomainUrl returns links with domain urls") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package no.ndla.imageapi.service
import no.ndla.common.CirceUtil
import no.ndla.common.model.domain.article.Copyright
import no.ndla.common.model.domain as common
import no.ndla.common.model.domain.AiGenerated
import no.ndla.common.model.domain.ContributorType
import no.ndla.imageapi.model.api.ImageMetaInformationV2DTO
import no.ndla.imageapi.model.domain.{ImageContentType, ImageFileData, ImageMetaInformation, ModelReleasedStatus}
Expand Down Expand Up @@ -73,7 +74,8 @@ class ReadServiceTest extends UnitSuite with TestEnvironment {
| },
| "tags":{"tags":["rovdyr","elg"],"language":"nb"},
| "caption":{"caption":"Elg i busk","language":"nb"},
| "supportedLanguages":["nb"]
| "supportedLanguages":["nb"],
| "aiGenerated": "No"
|}""".stripMargin

val expectedObject: ImageMetaInformationV2DTO = CirceUtil.unsafeParseAs[api.ImageMetaInformationV2DTO](expectedBody)
Expand Down Expand Up @@ -111,6 +113,7 @@ class ReadServiceTest extends UnitSuite with TestEnvironment {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

when(imageRepository.withId(1)).thenReturn(Success(Some(imageElg)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ package no.ndla.imageapi.service
import no.ndla.common.errors.{ValidationException, ValidationMessage}
import no.ndla.common.model.NDLADate
import no.ndla.common.model.domain.article.Copyright
import no.ndla.common.model.domain.{Author, ContributorType, Tag, UploadedFile}
import no.ndla.common.model.domain.{AiGenerated, Author, ContributorType, Tag, UploadedFile}
import no.ndla.imageapi.model.domain.*
import no.ndla.imageapi.{TestEnvironment, UnitSuite}
import no.ndla.mapping.License.CC_BY
Expand Down Expand Up @@ -57,6 +57,7 @@ class ValidationServiceTest extends UnitSuite with TestEnvironment {
modelReleased = ModelReleasedStatus.YES,
editorNotes = Seq.empty,
inactive = false,
aiGenerated = AiGenerated.No,
)

override def beforeEach(): Unit = {
Expand Down
Loading
Loading