Skip to content

Instantly share code, notes, and snippets.

@yongjhih
Last active November 8, 2023 04:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yongjhih/4e0db6b044b7595026779c1514eb0779 to your computer and use it in GitHub Desktop.
Save yongjhih/4e0db6b044b7595026779c1514eb0779 to your computer and use it in GitHub Desktop.
/**
* ```
* val giphyRepository = Retrofit.Builder()
* .baseUrl("https://api.giphy.com/")
* .addConverterFactory(Json {
* ignoreUnknownKeys = true
* }.asConverterFactory(contentType))
* .build()
* .create<GiphyRepository>()
*
* for (req in giphyRepository.searchSequence("cat").take(3)) {
* try {
* val res = req()
* Timber.v("${res}")
* } catch (e: Exception) {
* Timber.e(e)
* }
* delay(3.seconds)
* }
* ```
*/
interface GiphyRepository {
@GET("v1/gifs/trending")
suspend fun getTrending(
@Query("api_key") apiKey: String = API_KEY,
): GiphyData
@GET("v1/gifs/search")
suspend fun search(
@Query("q") query: String,
@Query("offset") offset: Int? = null,
@Query("limit") limit: Int? = null,
@Query("api_key") api_key: String = API_KEY,
@Query("lang") lang: String? = null,
@Query("bundle") bundle: String? = null,
): GiphyData
}
fun GiphyRepository.searchFlow(query: String, offset: Int? = null): Flow<List<Giphy>> = flow {
var offset = offset ?: 0
while (true) {
val res = search(query, offset = offset)
val data = res.data
if (data.isNullOrEmpty()) break
emit(data)
offset = res.pagination?.offset ?: (offset + data.size)
}
}
fun GiphyRepository.searchSequence(query: String, offset: Int? = null): Sequence<suspend () -> List<Giphy>?> = sequence {
var offset = offset
while (true) {
var isEnd = false
yield(suspend {
val res = search(query, offset)
val data = res.data
val newOffset = (res.pagination?.offset ?: offset ?: 0) + (res.pagination?.count ?: data?.size ?: 0)
isEnd = data.isNullOrEmpty() || (offset ?: 0) == newOffset
offset = newOffset
data
})
if (isEnd) break
}
}
fun GiphyRepository.searchUrlImageFlow(query: String, offset: Int? = null): Flow<List<UrlImage>> =
searchFlow(query, offset).map { data -> data.map { it.images?.values?.toList() ?: emptyList() }.flatten() }
inline fun <reified T> Retrofit.create(): T = create(T::class.java)
val contentType = "application/json".toMediaType()
@Serializable
data class Giphy (
var id: String? = null,
var type: String? = null,
var images: Map<String, UrlImage>? = null,
)
@Serializable
data class GiphyImage (
var url: String? = null,
var width: Int? = null,
var height: Int? = null,
var size: Int = 0,
var mp4: String? = null,
var mp4_size: Int = 0,
var webp: String? = null,
var webp_size: Int = 0,
)
@Serializable
data class UrlImage (
var url: String? = null,
var width: Int? = null,
var height: Int? = null,
)
@Serializable
data class GiphyData(
var data: List<Giphy>? = null,
var meta: Meta? = null,
var pagination: Pagination? = null,
)
@Serializable
data class Meta(
var status: Int = 0,
var msg: String? = null,
var response_id: String? = null,
)
@Serializable
data class Pagination(
var total_count: Int = 0,
var count: Int = 0,
var offset: Int = 0,
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment