חיפוש תמונות ב pixabay מתוך סקאלה

23/06/2024

בזכות ChatGPT לקח לי שלוש דקות להפוך את התיעוד של ה API של pixabay להגדרות טיפוסים בסקאלה, לפחות עבור התשובות שמקבלים מה API. זה כבר שיפור משמעותי לעומת החיים לפני ChatGPT בהם הייתי צריך לבנות לבד את הגדרות הטיפוסים או לוותר על Type Safety. אבל לצערי זה עדיין לא מספיק.

שתי הבעיות שנשארו לי עם כתיבת הגדרות הטיפוסים לבד הן:

  1. אם דברים ישתנו בעתיד אני אצטרך לעקוב אחרי השינויים ולעדכן את הקוד.

  2. בגלל אילוצי החיים, בניתי רק הגדרות טיפוסים לדברים שהייתי צריך. הרחבות עתידיות יכריחו אותי לעבור שוב בתיעוד ולרענן את הקוד.

הצד השני של הסיפור הוא שספריה מסודרת יכולה להיות לא מספיק מתוחזקת, כך שפיצ'רים שזמינים ב API לא יהיו זמינים עבור הקוד שלנו רק בגלל הבחירה להשתמש בספריית צד-שלישי ולא לגשת דרך ממשק REST.

בינתיים וכל עוד אני כותב בסקאלה הסיכוי שמישהו ידאג לי לספריה מסודרת רק יורד עם כל יום שעובר. אם במקרה אתם מגיעים לפה וצריכים קוד סקאלה לעבודה עם פיקסאביי מוזמנים להשתמש בזה בתור בסיס:

package dictionary.images

import com.typesafe.scalalogging.Logger
import common.ClaudeSyncClient.getClass
import io.circe.generic.auto.*
import io.circe.parser.*
import sttp.client3.*
import sttp.client3.circe.*

import sttp.model.Uri

import scala.util.chaining.*

case class ImageHit(id: Int,
                     pageURL: String,
                     `type`: String,
                     tags: String,
                     previewURL: String,
                     previewWidth: Int,
                     previewHeight: Int,
                     webformatURL: String,
                     webformatWidth: Int,
                     webformatHeight: Int,
                     largeImageURL: String,
                     imageWidth: Int,
                     imageHeight: Int,
                     imageSize: Int,
                     views: Int,
                     downloads: Int,
                     collections: Int,
                     likes: Int,
                     comments: Int,
                     user_id: Int,
                     user: String,
                     userImageURL: String)

case class ApiResponse(total: Int,
                        totalHits: Int,
                        hits: List[ImageHit])

object Pixabay {
  private val API_KEY: String = System.getenv("PIXABAY_API_KEY")
  val client: SimpleHttpClient = SimpleHttpClient()
  val logger: Logger = Logger(getClass)

  def searchImages(query: String): ApiResponse =
    val queryParams = Map(
      "key" -> API_KEY,
      "q" -> query,
      "image_type" -> "photo",
      "page" -> "1"
    )
    val baseUrl = uri"https://pixabay.com/api/"
    val uriWithParams: Uri = uri"$baseUrl?$queryParams"
    println(uriWithParams)
    basicRequest
      .get(uriWithParams)
      .response(asJson[ApiResponse])
      .pipe(client.send)
      .body match
        case Right(response) => response
        case Left(err) =>
          logger.error("Pixabay error: ", err)
          throw Exception(s"Error getting images from pixabay", err)

  @main
  def testImageSearchPixabay(): Unit =
    val response = searchImages("raisin")
    println(response.hits.head.previewURL)

}

נ.ב. מכל מיני סיבות של סקאלה וקסמים של JSON שאני לא מספיק מבין, בשביל שהקוד יעבוד יש צורך להוסיף את השורה הבאה ל build.sbt. אם מישהו מהקוראים או הקוראות יודעים לספר לי יותר על זה אשמח לשמוע בתגובות:

scalacOptions ++= Seq("-Xmax-inlines", "100")