Best Fuel code snippet using com.github.kittinunf.fuel.core.requests.UploadRequest.Request.upload
FuelManager.kt
Source:FuelManager.kt
1package com.github.kittinunf.fuel.core2import com.github.kittinunf.fuel.core.Client.Hook3import com.github.kittinunf.fuel.core.RequestFactory.PathStringConvertible4import com.github.kittinunf.fuel.core.RequestFactory.RequestConvertible5import com.github.kittinunf.fuel.core.interceptors.ParameterEncoder6import com.github.kittinunf.fuel.core.interceptors.redirectResponseInterceptor7import com.github.kittinunf.fuel.core.requests.DownloadRequest8import com.github.kittinunf.fuel.core.requests.UploadRequest9import com.github.kittinunf.fuel.core.requests.download10import com.github.kittinunf.fuel.core.requests.upload11import com.github.kittinunf.fuel.toolbox.HttpClient12import com.github.kittinunf.fuel.util.readWriteLazy13import java.net.Proxy14import java.security.KeyStore15import java.util.concurrent.Executor16import java.util.concurrent.ExecutorService17import java.util.concurrent.Executors18import javax.net.ssl.HostnameVerifier19import javax.net.ssl.HttpsURLConnection20import javax.net.ssl.SSLContext21import javax.net.ssl.SSLSocketFactory22import javax.net.ssl.TrustManagerFactory23typealias FoldableRequestInterceptor = (RequestTransformer) -> RequestTransformer24typealias FoldableResponseInterceptor = (ResponseTransformer) -> ResponseTransformer25class FuelManager : RequestFactory, RequestFactory.Convenience {26 var client: Client by readWriteLazy { HttpClient(proxy, hook = hook) }27 var proxy: Proxy? = null28 var basePath: String? = null29 var timeoutInMillisecond: Int = 15_00030 var timeoutReadInMillisecond: Int = timeoutInMillisecond31 var progressBufferSize: Int = DEFAULT_BUFFER_SIZE32 var hook: Hook = DefaultHook()33 var baseHeaders: Map<String, String>? = null34 var baseParams: Parameters = emptyList()35 var keystore: KeyStore? = null36 var socketFactory: SSLSocketFactory by readWriteLazy {37 keystore?.let {38 val trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())39 trustFactory.init(it)40 val sslContext = SSLContext.getInstance("SSL")41 sslContext.init(null, trustFactory.trustManagers, null)42 sslContext.socketFactory43 } ?: HttpsURLConnection.getDefaultSSLSocketFactory()44 }45 var hostnameVerifier: HostnameVerifier by readWriteLazy {46 HttpsURLConnection.getDefaultHostnameVerifier()47 }48 // background executionOptions49 var executorService: ExecutorService by readWriteLazy {50 Executors.newCachedThreadPool { command ->51 Thread(command).also { thread ->52 thread.priority = Thread.NORM_PRIORITY53 thread.isDaemon = true54 }55 }56 }57 private val requestInterceptors: MutableList<FoldableRequestInterceptor> =58 mutableListOf(ParameterEncoder)59 private val responseInterceptors: MutableList<FoldableResponseInterceptor> =60 mutableListOf(redirectResponseInterceptor(this))61 // callback executionOptions62 var callbackExecutor: Executor by readWriteLazy { createEnvironment().callbackExecutor }63 var forceMethods: Boolean = false64 /**65 * Make a request using [method] to [path] with [parameters]66 *67 * @see FuelManager.instance68 * @see FuelManager.applyOptions69 *70 * @param method [Method] the HTTP method to make the request with71 * @param path [String] the absolute url or relative to [FuelManager.instance] basePath72 * @param parameters [Parameters?] list of parameters73 *74 * @return [Request] the request75 */76 override fun request(method: Method, path: String, parameters: Parameters?): Request {77 val request = request(Encoding(78 httpMethod = method,79 urlString = path,80 baseUrlString = basePath,81 parameters = if (parameters == null) baseParams else baseParams + parameters82 ).request)83 return applyOptions(request)84 }85 /**86 * Make a request using [method] to [convertible]'s path with [parameters]87 *88 * @see FuelManager.instance89 * @see RequestFactory(Method, String, Parameters?)90 *91 * @param method [Method] the HTTP method to make the request with92 * @param convertible [PathStringConvertible]93 * @param parameters [Parameters?] list of parameters94 *95 * @return [Request] the request96 */97 override fun request(method: Method, convertible: PathStringConvertible, parameters: Parameters?): Request =98 request(method, convertible.path, parameters)99 /**100 * Make a request using from [convertible]101 *102 * @param convertible [RequestConvertible] the instance that can be turned into a [Request]103 * @return [Request] the request104 */105 override fun request(convertible: RequestConvertible): Request = applyOptions(convertible.request)106 /**107 * Create a [method] [Request] to [path] with [parameters], which can download to a file108 *109 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path110 * @param method [Method] the method to download with, defaults to [Method.GET]111 * @param parameters [Parameters] the optional parameters112 * @return [DownloadRequest] the request (extended for download)113 */114 override fun download(path: String, method: Method, parameters: Parameters?): DownloadRequest {115 val request = Encoding(116 httpMethod = method,117 urlString = path,118 baseUrlString = basePath,119 parameters = if (parameters == null) baseParams else baseParams + parameters120 ).request121 return applyOptions(request).download()122 }123 /**124 * Create a [method] [Request] to [path] with [parameters], which can upload blobs and Data Parts125 *126 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path127 * @param method [Method] the method to upload with, defaults to [Method.POST]128 * @param parameters [Parameters] the optional parameters129 * @return [UploadRequest] the request (extended for upload)130 */131 override fun upload(path: String, method: Method, parameters: Parameters?): UploadRequest {132 val request = Encoding(133 httpMethod = method,134 urlString = path,135 baseUrlString = basePath,136 parameters = if (parameters == null) baseParams else baseParams + parameters137 ).request138 return applyOptions(request).upload()139 }140 fun addRequestInterceptor(interceptor: FoldableRequestInterceptor): FuelManager {141 requestInterceptors += interceptor142 return this143 }144 fun addResponseInterceptor(interceptor: FoldableResponseInterceptor): FuelManager {145 responseInterceptors += interceptor146 return this147 }148 fun removeRequestInterceptor(interceptor: FoldableRequestInterceptor): FuelManager {149 requestInterceptors -= interceptor150 return this151 }152 fun removeResponseInterceptor(interceptor: FoldableResponseInterceptor): FuelManager {153 responseInterceptors -= interceptor154 return this155 }156 fun removeAllRequestInterceptors(): FuelManager {157 requestInterceptors.clear()158 return this159 }160 fun removeAllResponseInterceptors(): FuelManager {161 responseInterceptors.clear()162 return this163 }164 private fun applyOptions(request: Request): Request {165 // Sets base headers ONLY if they are not set166 val unsetBaseHeaders = request.headers.keys.fold(Headers.from(baseHeaders.orEmpty())) {167 result, it -> result.remove(it); result168 }169 return request.header(unsetBaseHeaders).apply {170 executionOptions = RequestExecutionOptions(171 client = client,172 socketFactory = socketFactory,173 hostnameVerifier = hostnameVerifier,174 callbackExecutor = callbackExecutor,175 requestTransformer = requestInterceptors.foldRight({ r: Request -> r }) { f, acc -> f(acc) },176 responseTransformer = responseInterceptors.foldRight({ _: Request, res: Response -> res }) { f, acc -> f(acc) },177 executorService = executorService178 ).also { executor ->179 executor.timeoutInMillisecond = timeoutInMillisecond180 executor.timeoutReadInMillisecond = timeoutReadInMillisecond181 executor.forceMethods = forceMethods182 }183 }184 }185 companion object {186 // manager187 var instance by readWriteLazy { FuelManager() }188 val progressBufferSize: Int get() = instance.progressBufferSize189 }190 /**191 * Create a [Method.GET] [Request] to [path] with [parameters]192 *193 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path194 * @param parameters [Parameters] the optional parameters195 * @return [Request] the request196 */197 override fun get(path: String, parameters: Parameters?): Request =198 request(Method.GET, path, parameters)199 /**200 * Create a [Method.GET] [Request] to [PathStringConvertible.path] with [parameters]201 *202 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path203 * @param parameters [Parameters] the optional parameters204 * @return [Request] the request205 */206 override fun get(convertible: PathStringConvertible, parameters: Parameters?): Request =207 request(Method.GET, convertible, parameters)208 /**209 * Create a [Method.POST] [Request] to [path] with [parameters]210 *211 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path212 * @param parameters [Parameters] the optional parameters213 * @return [Request] the request214 */215 override fun post(path: String, parameters: Parameters?): Request =216 request(Method.POST, path, parameters)217 /**218 * Create a [Method.POST] [Request] to [PathStringConvertible.path] with [parameters]219 *220 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path221 * @param parameters [Parameters] the optional parameters222 * @return [Request] the request223 */224 override fun post(convertible: PathStringConvertible, parameters: Parameters?): Request =225 request(Method.POST, convertible, parameters)226 /**227 * Create a [Method.PUT] [Request] to [path] with [parameters]228 *229 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path230 * @param parameters [Parameters] the optional parameters231 * @return [Request] the request232 */233 override fun put(path: String, parameters: Parameters?): Request =234 request(Method.PUT, path, parameters)235 /**236 * Create a [Method.PUT] [Request] to [PathStringConvertible.path] with [parameters]237 *238 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path239 * @param parameters [Parameters] the optional parameters240 * @return [Request] the request241 */242 override fun put(convertible: PathStringConvertible, parameters: Parameters?): Request =243 request(Method.PUT, convertible, parameters)244 /**245 * Create a [Method.PATCH] [Request] to [path] with [parameters]246 *247 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path248 * @param parameters [Parameters] the optional parameters249 * @return [Request] the request250 */251 override fun patch(path: String, parameters: Parameters?): Request =252 request(Method.PATCH, path, parameters)253 /**254 * Create a [Method.PATCH] [Request] to [PathStringConvertible.path] with [parameters]255 *256 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path257 * @param parameters [Parameters] the optional parameters258 * @return [Request] the request259 */260 override fun patch(convertible: PathStringConvertible, parameters: Parameters?): Request =261 request(Method.PATCH, convertible, parameters)262 /**263 * Create a [Method.DELETE] [Request] to [path] with [parameters]264 *265 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path266 * @param parameters [Parameters] the optional parameters267 * @return [Request] the request268 */269 override fun delete(path: String, parameters: Parameters?): Request =270 request(Method.DELETE, path, parameters)271 /**272 * Create a [Method.DELETE] [Request] to [PathStringConvertible.path] with [parameters]273 *274 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path275 * @param parameters [Parameters] the optional parameters276 * @return [Request] the request277 */278 override fun delete(convertible: PathStringConvertible, parameters: Parameters?): Request =279 request(Method.DELETE, convertible, parameters)280 /**281 * Create a [method] [Request] to [PathStringConvertible.path] with [parameters], which can download to a file282 *283 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path284 * @param method [Method] the method to download with, defaults to [Method.GET]285 * @param parameters [Parameters] the optional parameters286 * @return [DownloadRequest] the request (extended for download)287 */288 override fun download(convertible: PathStringConvertible, method: Method, parameters: Parameters?): DownloadRequest =289 download(convertible.path, method, parameters)290 /**291 * Create a [method] [Request] to [PathStringConvertible.path] with [parameters], which can upload blobs and292 * Data Parts293 *294 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path295 * @param method [Method] the method to upload with, defaults to [Method.POST]296 * @param parameters [Parameters] the optional parameters297 * @return [UploadRequest] the request (extended for upload)298 */299 override fun upload(convertible: PathStringConvertible, method: Method, parameters: Parameters?): UploadRequest =300 upload(convertible.path, method, parameters)301 /**302 * Create a [Method.HEAD] [Request] to [path] with [parameters]303 *304 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path305 * @param parameters [Parameters] the optional parameters306 * @return [Request] the request307 */308 override fun head(path: String, parameters: Parameters?): Request =309 request(Method.HEAD, path, parameters)310 /**311 * Create a [Method.HEAD] [Request] to [PathStringConvertible.path] with [parameters]312 *313 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path314 * @param parameters [Parameters] the optional parameters315 * @return [Request] the request316 */317 override fun head(convertible: PathStringConvertible, parameters: Parameters?): Request =318 request(Method.HEAD, convertible, parameters)319 /**320 * Resets this FuelManager to a clean instance321 */322 fun reset(): FuelManager {323 val clean = FuelManager()324 client = clean.client325 proxy = clean.proxy326 basePath = clean.basePath327 timeoutInMillisecond = clean.timeoutInMillisecond328 timeoutReadInMillisecond = clean.timeoutReadInMillisecond329 baseHeaders = clean.baseHeaders330 baseParams = clean.baseParams331 keystore = clean.keystore332 socketFactory = clean.socketFactory333 hostnameVerifier = clean.hostnameVerifier334 executorService = clean.executorService335 requestInterceptors.apply {336 clear()337 addAll(clean.requestInterceptors)338 }339 responseInterceptors.apply {340 clear()341 addAll(clean.responseInterceptors)342 }343 callbackExecutor = clean.callbackExecutor344 return this345 }346}...
Zendesk.kt
Source:Zendesk.kt
1/*2 * SPDX-License-Identifier: Apache-2.03 *4 * Copyright 2020 Bilal Makhlouf.5 *6 * Licensed under the Apache License, Version 2.0 (the "License");7 * you may not use this file except in compliance with the License.8 * You may obtain a copy of the License at9 *10 * https://www.apache.org/licenses/LICENSE-2.011 *12 * Unless required by applicable law or agreed to in writing, software13 * distributed under the License is distributed on an "AS IS" BASIS,14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.15 * See the License for the specific language governing permissions and16 * limitations under the License.17 */18package com.saagie.htmltozendeskuploader.zendesk19import arrow.core.Either20import arrow.core.Tuple221import arrow.core.extensions.either.applicative.applicative22import arrow.core.extensions.list.traverse.sequence23import arrow.core.extensions.tuple2.traverse.sequence24import arrow.core.firstOrNone25import arrow.core.fix26import arrow.core.flatMap27import arrow.core.handleErrorWith28import arrow.core.left29import arrow.core.right30import arrow.core.rightIfNotNull31import arrow.core.toOption32import arrow.core.toT33import com.github.kittinunf.fuel.Fuel34import com.github.kittinunf.fuel.core.FileDataPart35import com.github.kittinunf.fuel.core.InlineDataPart36import com.github.kittinunf.fuel.core.Method37import com.github.kittinunf.fuel.core.Method.DELETE38import com.github.kittinunf.fuel.core.Method.GET39import com.github.kittinunf.fuel.core.Method.POST40import com.github.kittinunf.fuel.core.Method.PUT41import com.github.kittinunf.fuel.core.Request42import com.github.kittinunf.fuel.core.ResponseDeserializable43import com.github.kittinunf.fuel.core.extensions.authentication44import com.github.kittinunf.fuel.core.extensions.jsonBody45import com.github.kittinunf.fuel.core.requests.UploadRequest46import com.github.kittinunf.fuel.core.requests.upload47import com.saagie.htmltozendeskuploader.model.Article48import com.saagie.htmltozendeskuploader.model.ArticleAttachment49import com.saagie.htmltozendeskuploader.model.ExistingSection50import com.saagie.htmltozendeskuploader.model.NewSection51import com.saagie.htmltozendeskuploader.model.Translation52import com.saagie.htmltozendeskuploader.zendesk.HtmlToZendeskError.ZendeskRequestError.ResourceDoesNotExist53import com.saagie.htmltozendeskuploader.zendesk.HtmlToZendeskError.ZendeskRequestError.UnexpectedRequestError54import com.saagie.htmltozendeskuploader.zendesk.HtmlToZendeskError.ZendeskRequestError.UnexpectedRequestResult55import com.saagie.htmltozendeskuploader.zendesk.ZendeskRequest.DeleteSection56import java.io.File57import kotlin.reflect.KClass58sealed class ZendeskApiBody {59 data class SectionsBody(val sections: List<ExistingSection>) : ZendeskApiBody()60 data class NewSectionBody(val section: NewSection) : ZendeskApiBody()61 data class ExistingSectionBody(val section: ExistingSection) : ZendeskApiBody()62 data class ArticleBody(val article: Article) : ZendeskApiBody()63 data class ArticlesBody(val articles: List<Article>) : ZendeskApiBody()64 data class TranslationBody(val translation: Translation) : ZendeskApiBody()65 data class TranslationsBody(val translations: List<Translation>) : ZendeskApiBody()66 data class AttachmentIdsBody(val attachmentIds: List<Long>) : ZendeskApiBody()67 data class AttachmentBody(val articleAttachment: ArticleAttachment) : ZendeskApiBody()68 object EmptyBody : ZendeskApiBody()69}70sealed class ZendeskRequest<out T : ZendeskApiBody>(71 val method: Method,72 val path: String,73 val responseType: KClass<out T>,74 open val body: ZendeskApiBody = ZendeskApiBody.EmptyBody75) {76 open fun get(basePath: String) = Fuel.request(method, basePath + path, null)77 .apply {78 this@ZendeskRequest.body.toOption().map { jsonBody(gson.toJson(it)) }79 }80 data class GetSections(val categoryId: Long) : ZendeskRequest<ZendeskApiBody.SectionsBody>(81 GET, "/categories/$categoryId/sections.json", ZendeskApiBody.SectionsBody::class82 )83 data class CreateSection(val categoryId: Long, val section: NewSection) :84 ZendeskRequest<ZendeskApiBody.ExistingSectionBody>(85 POST,86 "/categories/$categoryId/sections.json",87 ZendeskApiBody.ExistingSectionBody::class,88 ZendeskApiBody.NewSectionBody(section)89 )90 data class DeleteSection(val sectionId: Long) : ZendeskRequest<ZendeskApiBody.EmptyBody>(91 DELETE,92 "/sections/$sectionId.json",93 ZendeskApiBody.EmptyBody::class94 )95 data class CreateArticle(val article: Article) : ZendeskRequest<ZendeskApiBody.ArticleBody>(96 POST,97 "/sections/${article.parentSectionId}/articles.json",98 ZendeskApiBody.ArticleBody::class,99 ZendeskApiBody.ArticleBody(article)100 )101 data class GetArticles(val sectionId: Long) : ZendeskRequest<ZendeskApiBody.ArticlesBody>(102 GET,103 "/sections/$sectionId/articles.json",104 ZendeskApiBody.ArticlesBody::class105 )106 data class UploadAttachedImage(val filePath: String) : ZendeskRequest<ZendeskApiBody.AttachmentBody>(107 POST,108 "/articles/attachments.json",109 ZendeskApiBody.AttachmentBody::class110 ) {111 override fun get(basePath: String): UploadRequest = super.get(basePath).upload()112 .add(FileDataPart(name = "file", file = File(filePath)))113 .add(InlineDataPart(name = "inline", content = "true"))114 }115 data class LinkAttachedImage(val articleId: Long, val attachmentIds: List<Long>) :116 ZendeskRequest<ZendeskApiBody.EmptyBody>(117 POST,118 "/articles/$articleId/bulk_attachments.json",119 ZendeskApiBody.EmptyBody::class,120 ZendeskApiBody.AttachmentIdsBody(attachmentIds)121 )122 data class GetArticleTranslations(val articleId: Long, val locale: String) :123 ZendeskRequest<ZendeskApiBody.TranslationsBody>(124 GET,125 "/articles/$articleId/translations.json",126 ZendeskApiBody.TranslationsBody::class127 )128 data class UpdateArticleTranslation(val translation: Translation) :129 ZendeskRequest<ZendeskApiBody.EmptyBody>(130 PUT,131 "/articles/${translation.sourceId}/translations/${translation.locale}.json",132 ZendeskApiBody.EmptyBody::class,133 ZendeskApiBody.TranslationBody(translation)134 )135}136class Zendesk(137 val url: String,138 val user: String,139 val password: String,140 val categoryId: Long,141 val pattern: String? = null142) {143 fun createSectionOrOverwriteIfExist(section: NewSection) =144 (pattern?.let {145 getSectionWithPattern(it, section.parentSectionId)146 } ?: getSection(section.name, section.parentSectionId))147 .flatMap {148 DeleteSection(it.id)149 .run()150 .handleErrorWith {151 when (it) {152 is ResourceDoesNotExist -> Unit.right()153 else -> it.left()154 }155 }156 .also { println("Section for version ${section.name} already exists. Deleting it.") }157 .map { section }158 }159 .handleErrorWith {160 when (it) {161 is ResourceDoesNotExist -> section.right()162 else -> it.left()163 }164 }.flatMap { createSection(it) }165 .map { it.id }166 fun createArticle(article: Article) =167 uploadImages(article)168 .map { attachmentsMapping ->169 attachmentsMapping toT article.replaceImgUrlWithAttachmentUrl(attachmentsMapping)170 }171 .flatmapTupleRight(::postArticle)172 .flatMap { (attachments, articleId) ->173 if (attachments.isNotEmpty())174 linkAttachmentsToArticle(attachments.values, articleId)175 else176 Either.right(article)177 }178 fun publishSection(section: ExistingSection) =179 getArticles(section.id)180 .flatMap { articles ->181 articles.map {182 publishArticle(it)183 }.sequence(Either.applicative()).fix()184 }185 .map { Unit }186 private fun getArticleTranslations(articleId: Long) =187 ZendeskRequest.GetArticleTranslations(articleId, "en-us").run()188 .map {189 it.translations190 }191 private fun getArticles(sectionId: Long) =192 ZendeskRequest.GetArticles(sectionId).run()193 .map {194 it.articles195 }196 private fun updateTranslation(translation: Translation) =197 ZendeskRequest.UpdateArticleTranslation(translation).run()198 private fun publishArticle(article: Article) =199 article.id.rightIfNotNull { HtmlToZendeskError.MissingArticleId }200 .flatMap { getArticleTranslations(it) }201 .flatMap { translations ->202 translations.map { translation ->203 updateTranslation(translation.copy(draft = false))204 }.sequence(Either.applicative()).fix()205 }206 .map { Unit }207 private fun uploadArticleImage(path: String) =208 ZendeskRequest.UploadAttachedImage(path).run()209 .map { it.articleAttachment }210 private fun uploadImages(article: Article) =211 article.getBodyImages()212 .map { it to uploadArticleImage("${article.path.parent}/$it") }213 .map { (imgName, uploadResult) ->214 uploadResult.fold({215 it.left()216 }, {217 (imgName to it).right()218 })219 }220 .sequence(Either.applicative()).fix().map { it.fix().toMap() }221 private fun linkAttachmentsToArticle(attachments: Collection<ArticleAttachment>, articleId: Long) =222 ZendeskRequest.LinkAttachedImage(articleId, attachments.map(ArticleAttachment::id)).run()223 private fun postArticle(article: Article) =224 ZendeskRequest.CreateArticle(article).run()225 .flatMap {226 it.article.id.rightIfNotNull {227 UnexpectedRequestResult("The id of the article that has been created is not set. $it ")228 }229 }230 fun getSection(name: String, parentSectionId: Long? = null) =231 ZendeskRequest.GetSections(categoryId).run()232 .flatMap {233 it.sections.firstOrNone { it.name == name && it.parentSectionId == parentSectionId }234 .toEither { ResourceDoesNotExist }235 }236 private fun getSectionWithPattern(pattern: String, parentSectionId: Long? = null) =237 ZendeskRequest.GetSections(categoryId).run()238 .flatMap {239 it.sections.firstOrNone { section ->240 pattern.toRegex().containsMatchIn(section.name) && section.parentSectionId == parentSectionId241 }.toEither { ResourceDoesNotExist }242 }243 private fun createSection(section: NewSection) =244 ZendeskRequest.CreateSection(categoryId, section)245 .run()246 .map { it.section }247 class ZendeskResponseDeserializable2<T : ZendeskApiBody>(val responseType: KClass<out T>) :248 ResponseDeserializable<T> {249 override fun deserialize(content: String): T = when (responseType) {250 ZendeskApiBody.EmptyBody::class -> ZendeskApiBody.EmptyBody as T251 else -> gson.fromJson(content, responseType.java)252 }253 }254 private fun <T : ZendeskApiBody> ZendeskRequest<T>.run(requestConfigBlock: Request.() -> Unit = {}) =255 get(url)256 .apply(requestConfigBlock)257 .also { println(it) }258 .authentication()259 .basic(user, password)260 .responseObject(ZendeskResponseDeserializable2(responseType))261 .third262 .fold(263 { it.right() },264 {265 when (it.response.statusCode) {266 404 -> ResourceDoesNotExist.left()267 else -> UnexpectedRequestError(it).left()268 }269 })270}271private fun <A, B, C, D> Either<A, Tuple2<B, C>>.flatmapTupleRight(block: (C) -> Either<A, D>) = flatMap {272 it.map(block).sequence(Either.applicative()).fix().map { it.fix() }273}...
RequestFactory.kt
Source:RequestFactory.kt
1package com.github.kittinunf.fuel.core2import com.github.kittinunf.fuel.Fuel3import com.github.kittinunf.fuel.core.requests.DownloadRequest4import com.github.kittinunf.fuel.core.requests.UploadRequest5interface RequestFactory {6 /**7 * Make a request using [method] to [convertible]'s path with [parameters]8 *9 * @see FuelManager.instance10 * @see RequestFactory(Method, String, Parameters?)11 *12 * @param method [Method] the HTTP method to make the request with13 * @param convertible [PathStringConvertible]14 * @param parameters [Parameters?] list of parameters15 *16 * @return [Request] the request17 */18 fun request(method: Method, convertible: PathStringConvertible, parameters: Parameters? = null): Request19 /**20 * Make a request using [method] to [path] with [parameters]21 *22 * @see FuelManager.instance23 * @see FuelManager.request24 *25 * @param method [Method] the HTTP method to make the request with26 * @param path [String] the absolute url or relative to [FuelManager.instance] basePath27 * @param parameters [Parameters?] list of parameters28 *29 * @return [Request] the request30 */31 fun request(method: Method, path: String, parameters: Parameters? = null): Request32 /**33 * Make a request using from [convertible]34 *35 * @param convertible [RequestConvertible] the instance that can be turned into a [Request]36 * @return [Request] the request37 */38 fun request(convertible: RequestConvertible): Request39 /**40 * Anything that is a [PathStringConvertible] can be used as [path] parameter with [Fuel]41 */42 interface PathStringConvertible {43 val path: String44 }45 /**46 * Anything that is [RequestConvertible] can be used as [request] with [Fuel.request]47 */48 interface RequestConvertible {49 val request: Request50 }51 interface Convenience : RequestFactory {52 /**53 * Create a [method] [Request] to [path] with [parameters], which can download to a file54 *55 * @parameters path [String] the absolute or relative to [FuelManager.instance]' base-path path56 * @parameters method [Method] the method to download with, defaults to [Method.GET]57 * @parameters parameters [Parameters] the optional parameters58 * @return [DownloadRequest] the request (extended for download)59 */60 fun download(path: String, method: Method = Method.GET, parameters: Parameters? = null): DownloadRequest61 /**62 * Create a [method] [Request] to [PathStringConvertible.path] with [parameters], which can download to a file63 *64 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path65 * @param method [Method] the method to download with, defaults to [Method.GET]66 * @param parameters [Parameters] the optional parameters67 * @return [DownloadRequest] the request (extended for download)68 */69 fun download(convertible: PathStringConvertible, method: Method = Method.GET, parameters: Parameters? = null): DownloadRequest70 /**71 * Create a [method] [Request] to [PathStringConvertible.path] with [parameters], which can upload blobs and72 * Data Parts73 *74 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path75 * @param method [Method] the method to upload with, defaults to [Method.POST]76 * @param parameters [Parameters] the optional parameters77 * @return [UploadRequest] the request (extended for upload)78 */79 fun upload(convertible: PathStringConvertible, method: Method = Method.POST, parameters: Parameters? = null): UploadRequest80 /**81 * Create a [method] [Request] to [path] with [parameters], which can upload blobs and Data Parts82 *83 * @parameters path [String] the absolute or relative to [FuelManager.instance]' base-path path84 * @parameters method [Method] the method to upload with, defaults to [Method.POST]85 * @parameters parameters [Parameters] the optional parameters86 * @return [UploadRequest] the request (extended for upload)87 */88 fun upload(path: String, method: Method = Method.POST, parameters: Parameters? = null): UploadRequest89 /**90 * Create a [Method.GET] [Request] to [path] with [parameters]91 *92 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path93 * @param parameters [Parameters] the optional parameters94 * @return [Request] the request95 */96 fun get(path: String, parameters: Parameters? = null): Request97 /**98 * Create a [Method.GET] [Request] to [PathStringConvertible.path] with [parameters]99 *100 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path101 * @param parameters [Parameters] the optional parameters102 * @return [Request] the request103 */104 fun get(convertible: PathStringConvertible, parameters: Parameters? = null): Request105 /**106 * Create a [Method.POST] [Request] to [path] with [parameters]107 *108 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path109 * @param parameters [Parameters] the optional parameters110 * @return [Request] the request111 */112 fun post(path: String, parameters: Parameters? = null): Request113 /**114 * Create a [Method.POST] [Request] to [PathStringConvertible.path] with [parameters]115 *116 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path117 * @param parameters [Parameters] the optional parameters118 * @return [Request] the request119 */120 fun post(convertible: PathStringConvertible, parameters: Parameters? = null): Request121 /**122 * Create a [Method.PUT] [Request] to [path] with [parameters]123 *124 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path125 * @param parameters [Parameters] the optional parameters126 * @return [Request] the request127 */128 fun put(path: String, parameters: Parameters? = null): Request129 /**130 * Create a [Method.PUT] [Request] to [PathStringConvertible.path] with [parameters]131 *132 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path133 * @param parameters [Parameters] the optional parameters134 * @return [Request] the request135 */136 fun put(convertible: PathStringConvertible, parameters: Parameters? = null): Request137 /**138 * Create a [Method.PATCH] [Request] to [path] with [parameters]139 *140 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path141 * @param parameters [Parameters] the optional parameters142 * @return [Request] the request143 */144 fun patch(path: String, parameters: Parameters? = null): Request145 /**146 * Create a [Method.PATCH] [Request] to [PathStringConvertible.path] with [parameters]147 *148 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path149 * @param parameters [Parameters] the optional parameters150 * @return [Request] the request151 */152 fun patch(convertible: PathStringConvertible, parameters: Parameters? = null): Request153 /**154 * Create a [Method.DELETE] [Request] to [path] with [parameters]155 *156 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path157 * @param parameters [Parameters] the optional parameters158 * @return [Request] the request159 */160 fun delete(path: String, parameters: Parameters? = null): Request161 /**162 * Create a [Method.DELETE] [Request] to [PathStringConvertible.path] with [parameters]163 *164 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path165 * @param parameters [Parameters] the optional parameters166 * @return [Request] the request167 */168 fun delete(convertible: PathStringConvertible, parameters: Parameters? = null): Request169 /**170 * Create a [Method.HEAD] [Request] to [path] with [parameters]171 *172 * @param path [String] the absolute or relative to [FuelManager.instance]' base-path path173 * @param parameters [Parameters] the optional parameters174 * @return [Request] the request175 */176 fun head(path: String, parameters: Parameters? = null): Request177 /**178 * Create a [Method.HEAD] [Request] to [PathStringConvertible.path] with [parameters]179 *180 * @param convertible [PathStringConvertible] the absolute or relative to [FuelManager.instance]' base-path path181 * @param parameters [Parameters] the optional parameters182 * @return [Request] the request183 */184 fun head(convertible: PathStringConvertible, parameters: Parameters? = null): Request185 }186}...
UploadBody.kt
Source:UploadBody.kt
1package com.github.kittinunf.fuel.core.requests2import com.github.kittinunf.fuel.core.Body3import com.github.kittinunf.fuel.core.DataPart4import com.github.kittinunf.fuel.core.FuelError5import com.github.kittinunf.fuel.core.Headers6import com.github.kittinunf.fuel.core.Response7import com.github.kittinunf.fuel.core.representationOfBytes8import java.io.ByteArrayInputStream9import java.io.ByteArrayOutputStream10import java.io.InputStream11import java.io.OutputStream12import java.nio.charset.Charset13internal class BoundaryMissing(request: UploadRequest) : FuelError(14 IllegalArgumentException(15 "The Request is missing the boundary parameter in its Content-Type.\n\n" +16 "This can happen if you manually overwrite the Content-Type but forget to set a boundary. The boundary is \n" +17 "normally set automatically when you call \"request.upload()\". Remove manually setting the Content-Type or \n" +18 "add the boundary parameter to the Content-Type for this request: \n\n" +19 "\trequest.header(Headers.ContentType, \"multipart/form-data; boundary=custom-boundary\")"20 ),21 Response.error(request.url)22)23internal data class UploadBody(val request: UploadRequest) : Body {24 private var inputAvailable: Boolean = true25 /**26 * Represents this body as a string27 * @param contentType [String] the type of the content in the body, or null if a guess is necessary28 * @return [String] the body as a string or a string that represents the body such as (empty) or (consumed)29 */30 override fun asString(contentType: String?) = representationOfBytes("multipart/form-data")31 /**32 * Returns if the body is consumed.33 * @return [Boolean] if true, `writeTo`, `toStream` and `toByteArray` may throw34 */35 override fun isConsumed() = !inputAvailable36 /**37 * Returns the body emptiness.38 * @return [Boolean] if true, this body is empty39 */40 override fun isEmpty() = false41 /**42 * Returns the body as an [InputStream].43 *44 * @note callers are responsible for closing the returned stream.45 * @note implementations may choose to make the [Body] `isConsumed` and can not be written or read from again.46 *47 * @return the body as input stream48 */49 override fun toStream(): InputStream {50 throw UnsupportedOperationException(51 "Conversion `toStream` is not supported on UploadBody, because the source is not a single single stream." +52 "Use `toByteArray` to write the contents to memory or `writeTo` to write the contents to a stream."53 )54 }55 /**56 * Returns the body as a [ByteArray].57 *58 * @note Because the body needs to be read into memory anyway, implementations may choose to make the [Body]59 * readable once more after calling this method, with the original [InputStream] being closed (and release its60 * resources). This also means that if an implementation choose to keep it around, `isConsumed` returns false.61 *62 * @return the entire body63 */64 override fun toByteArray(): ByteArray {65 return ByteArrayOutputStream(length?.toInt() ?: 32)66 .use { stream ->67 writeTo(stream)68 stream.toByteArray()69 }70 .also { result ->71 // The entire body is now in memory, and can act as a regular body72 request.body(DefaultBody.from(73 { ByteArrayInputStream(result) },74 { result.size.toLong() }75 ))76 }77 }78 /**79 * Writes the body to the [OutputStream].80 *81 * @note callers are responses for closing the [OutputStream].82 * @note implementations may choose to make the [Body] `isConsumed` and can not be written or read from again.83 * @note implementations are recommended to buffer the output stream if they can't ensure bulk writing.84 *85 * @param outputStream [OutputStream] the stream to write to86 * @return [Long] the number of bytes written87 */88 override fun writeTo(outputStream: OutputStream): Long {89 if (!inputAvailable) {90 throw FuelError.wrap(IllegalStateException(91 "The inputs have already been written to an output stream and can not be consumed again."92 ))93 }94 inputAvailable = false95 val lazyDataparts = request.dataParts96 return outputStream.buffered().let { stream ->97 // Parameters98 val parameterLength = request.parameters.sumByDouble { (name, data) ->99 writeParameter(stream, name, data).toDouble()100 }101 // Blobs / Files102 val filesWithHeadersLength = lazyDataparts.sumByDouble { lazyDataPart ->103 writeDataPart(stream, lazyDataPart(request)).toDouble()104 }105 // Sum and Trailer106 val writtenLength = 0L +107 parameterLength +108 filesWithHeadersLength +109 stream.writeBoundary() + stream.writeString("--") +110 stream.writeNewline()111 // This is a buffered stream, so flush what's remaining112 writtenLength.toLong().also { stream.flush() }113 }114 }115 /**116 * Returns the length of the body in bytes117 * @return [Long?] the length in bytes, null if it is unknown118 */119 override val length: Long? by lazy {120 (121 // Parameters size122 request.parameters.sumByDouble { (name, data) ->123 writeParameter(ByteArrayOutputStream(), name, data).toDouble()124 } +125 // Blobs / Files size126 request.dataParts.sumByDouble { lazyDataPart ->127 val dataPart = lazyDataPart(request)128 // Allow for unknown sizes129 val length = dataPart.contentLength ?: return@lazy null130 if (length == -1L) return@lazy -1L131 0.0 + writeDataPartHeader(ByteArrayOutputStream(), dataPart) + length + CRLF.size132 } +133 // Trailer size134 "--$boundary--".toByteArray(DEFAULT_CHARSET).size + CRLF.size135 ).toLong()136 }137 private val boundary: String by lazy {138 request[Headers.CONTENT_TYPE].lastOrNull()139 ?.let { Regex("boundary=([^\\s]+)").find(it)?.groupValues?.getOrNull(1)?.trim('"') }140 ?: throw BoundaryMissing(request)141 }142 private fun writeParameter(outputStream: OutputStream, name: String, data: Any?): Long {143 outputStream.apply {144 return 0L +145 writeBoundary() +146 writeNewline() +147 writeString("${Headers.CONTENT_DISPOSITION}: form-data; name=\"$name\"") +148 writeNewline() +149 writeString("${Headers.CONTENT_TYPE}: text/plain; charset=\"${DEFAULT_CHARSET.name()}\"") +150 writeNewline() +151 writeNewline() +152 writeString(data.toString()) +153 writeNewline()154 }155 }156 private fun writeDataPart(outputStream: OutputStream, dataPart: DataPart): Long {157 outputStream.apply {158 val headerLength = writeDataPartHeader(outputStream, dataPart)159 val dataLength = dataPart.inputStream().use { it.copyTo(this) }160 return headerLength + dataLength + writeNewline()161 }162 }163 private fun writeDataPartHeader(outputStream: OutputStream, dataPart: DataPart): Long {164 outputStream.apply {165 return 0L +166 writeBoundary() +167 writeNewline() +168 writeString("${Headers.CONTENT_DISPOSITION}: ${dataPart.contentDisposition}") +169 writeNewline() +170 writeString("${Headers.CONTENT_TYPE}: ${dataPart.contentType}") +171 writeNewline() +172 writeNewline()173 }174 }175 private fun OutputStream.writeNewline() = writeBytes(CRLF)176 private fun OutputStream.writeBytes(bytes: ByteArray) = write(bytes).let { bytes.size.toLong() }177 private fun OutputStream.writeString(string: String, charset: Charset = DEFAULT_CHARSET) = writeBytes(string.toByteArray(charset))178 private fun OutputStream.writeBoundary() = writeString("--$boundary")179 companion object {180 val DEFAULT_CHARSET = Charsets.UTF_8181 private val CRLF = "\r\n".toByteArray(DEFAULT_CHARSET)182 fun from(request: UploadRequest): Body {183 return UploadBody(request).apply {184 inputAvailable = true185 }186 }187 }188}...
UploadRequest.kt
Source:UploadRequest.kt
1package com.github.kittinunf.fuel.core.requests2import com.github.kittinunf.fuel.core.Blob3import com.github.kittinunf.fuel.core.DataPart4import com.github.kittinunf.fuel.core.Headers5import com.github.kittinunf.fuel.core.LazyDataPart6import com.github.kittinunf.fuel.core.ProgressCallback7import com.github.kittinunf.fuel.core.Request8import java.io.File9import java.net.URL10import java.util.UUID11class UploadRequest private constructor(private val wrapped: Request) : Request by wrapped {12 override val request: UploadRequest = this13 val dataParts: MutableCollection<LazyDataPart> = mutableListOf()14 private fun ensureBoundary() {15 val contentType = this[Headers.CONTENT_TYPE].lastOrNull()16 // Overwrite the current content type17 if (contentType.isNullOrBlank() || !contentType.startsWith("multipart/form-data") || !Regex("boundary=[^\\s]+").containsMatchIn(contentType)) {18 this[Headers.CONTENT_TYPE] = "multipart/form-data; boundary=\"${UUID.randomUUID()}\""19 return20 }21 }22 override fun toString() = "Upload[\n\r\t$wrapped\n\r]"23 /**24 * Add one or multiple [dataParts] callbacks to be invoked to get a [DataPart] to write to the [UploadBody]25 * @param dataParts [LazyDataPart] the callbacks26 */27 fun add(vararg dataParts: LazyDataPart) = dataParts.fold(this, UploadRequest::plus)28 /**29 * Add one or multiple [DataPart]s to the [UploadBody]30 * @param dataParts [DataPart] the parts31 */32 fun add(vararg dataParts: DataPart) = plus(dataParts.toList())33 /**34 * Add a [DataPart] callback to be invoked to get a [DataPart] to write to the [UploadBody]35 * @param dataPart [LazyDataPart] the callback36 */37 fun add(dataPart: LazyDataPart) = plus(dataPart)38 /**39 * Add a [DataPart] to be written to the [UploadBody]40 * @param dataPart [DataPart] the part41 */42 fun add(dataPart: DataPart) = plus(dataPart)43 /**44 * Add a [DataPart] callback to be invoked to get a [DataPart] to write to the [UploadBody]45 * @param dataPart [LazyDataPart] the callback46 */47 operator fun plus(dataPart: LazyDataPart) = this.also { dataParts.add(dataPart) }48 /**49 * Add a [DataPart] to be written to the [UploadBody]50 * @param dataPart [DataPart] the part51 */52 operator fun plus(dataPart: DataPart) = plus { dataPart }53 /**54 * Add all [dataParts] to be written to the [UploadBody]55 * @param dataParts [Iterable<DataPart>] the iterable that yields [DataPart]s56 */57 operator fun plus(dataParts: Iterable<DataPart>) = dataParts.fold(this, UploadRequest::plus)58 /**59 * Add a [ProgressCallback] to the [requestProgress]60 * @param progress [ProgressCallback] the callback61 */62 fun progress(progress: ProgressCallback) = requestProgress(progress)63 companion object {64 val FEATURE: String = UploadRequest::class.java.canonicalName65 /**66 * Enable [UploadRequest] for the passed in [request]67 *68 * @note this sets the Content-Type to multipart/form-data; boundary=uuid even when there was already a69 * Content-Type set, unless it's multipart/form-data with a valid boundary.70 *71 * @param request [Request] the request to enable this for72 * @return [UploadRequest] the enhanced request73 */74 fun enableFor(request: Request) = request.enabledFeatures75 .getOrPut(FEATURE) {76 UploadRequest(request)77 .apply { this.body(UploadBody.from(this)) }78 .apply { this.ensureBoundary() }79 } as UploadRequest80 }81 @Deprecated("Use request.add({ BlobDataPart(...) }, { ... }, ...) instead", ReplaceWith(""), DeprecationLevel.ERROR)82 fun blobs(@Suppress("DEPRECATION") blobsCallback: (Request, URL) -> Iterable<Blob>): UploadRequest =83 throw NotImplementedError("request.blobs has been removed. Use request.add({ BlobDataPart(...) }, { ... }, ...) instead.")84 @Deprecated("Use request.add { BlobDataPart(...) } instead", ReplaceWith("add(blobsCallback)"))85 fun blob(@Suppress("DEPRECATION") blobCallback: (Request, URL) -> Blob): UploadRequest =86 throw NotImplementedError("request.blob has been removed. Use request.add { BlobDataPart(...) } instead.")87 @Deprecated("Use request.add({ ... }, { ... }, ...) instead", ReplaceWith(""), DeprecationLevel.ERROR)88 fun dataParts(dataPartsCallback: (Request, URL) -> Iterable<DataPart>): UploadRequest =89 throw NotImplementedError("request.dataParts has been removed. Use request.add { XXXDataPart(...) } instead.")90 @Deprecated("Use request.add({ FileDataPart(...) }, { ... }, ...) instead", ReplaceWith(""), DeprecationLevel.ERROR)91 fun sources(sourcesCallback: (Request, URL) -> Iterable<File>): UploadRequest =92 throw NotImplementedError("request.sources has been removed. Use request.add({ BlobDataPart(...) }, { ... }, ...) instead.")93 @Deprecated("Use request.add { FileDataPart(...)} instead", ReplaceWith("add(sourceCallback)"), DeprecationLevel.ERROR)94 fun source(sourceCallback: (Request, URL) -> File): UploadRequest =95 throw NotImplementedError("request.source has been removed. Use request.add { FileDataPart(...) } instead.")96 @Deprecated("Set the name via DataPart (FileDataPart, InlineDataPart, BlobDataPart) instead", ReplaceWith(""), DeprecationLevel.ERROR)97 fun name(nameCallback: () -> String): UploadRequest =98 throw NotImplementedError("request.name has been removed. Set the name via DataPart (FileDataPart, InlineDataPart, BlobDataPart) instead")99 @Deprecated("Set the name via DataPart (FileDataPart, InlineDataPart, BlobDataPart) instead", ReplaceWith(""), DeprecationLevel.ERROR)100 fun name(newName: String): UploadRequest =101 throw NotImplementedError("request.name has been removed. Set the name via DataPart (FileDataPart, InlineDataPart, BlobDataPart) instead")102}103fun Request.upload(): UploadRequest = UploadRequest.enableFor(this)...
FileRepository.kt
Source:FileRepository.kt
1package xo.william.pixeldrain.repository2import android.util.Log3import androidx.lifecycle.*4import com.github.kittinunf.fuel.core.Request5import com.github.kittinunf.fuel.core.requests.UploadRequest6import xo.william.pixeldrain.api.FuelService7import xo.william.pixeldrain.database.File8import xo.william.pixeldrain.database.FileDao9import xo.william.pixeldrain.fileList.InfoModel10import com.github.kittinunf.result.Result11import kotlinx.serialization.decodeFromString12import kotlinx.serialization.json.Json13import xo.william.pixeldrain.fileList.InfoModelList14import java.io.InputStream15class FileRepository(private val fileDao: FileDao) {16 // Room executes all queries on a separate thread.17 private val fuelService = FuelService()18 private val format = Json { ignoreUnknownKeys = true }19 fun getDatabaseFiles(): LiveData<List<File>> {20 return fileDao.getAll()21 }22 fun insert(file: File) {23 fileDao.insert(file)24 }25 fun deleteFromDb(id: String) {26 return fileDao.deleteById(id)27 }28 fun uploadAnonPost(selectedFile: InputStream, fileName: String?): UploadRequest {29 return fuelService.uploadAnonFile(selectedFile, fileName)30 }31 fun uploadPost(selectedFile: InputStream, fileName: String?, authKey: String): UploadRequest {32 return fuelService.uploadFile(selectedFile, fileName, authKey)33 }34 fun loadFileInfo(file: File, loadedFiles: MutableLiveData<MutableList<InfoModel>>) {35 fuelService.getFileInfoById(file.id).responseString { _, _, result ->36 when (result) {37 is Result.Success -> {38 val infoFile = format.decodeFromString<InfoModel>(result.get())39 loadedFiles.value?.add(infoFile)40 loadedFiles.postValue(loadedFiles.value)41 }42 }43 }44 }45 fun loadApiFiles(loadedFiles: MutableLiveData<MutableList<InfoModel>>, authKey: String) {46 fuelService.getFiles(authKey).responseString { _, _, result ->47 when (result) {48 is Result.Success -> {49 val infoModelList = format.decodeFromString<InfoModelList>(result.get())50 loadedFiles.value?.addAll(infoModelList.files)51 loadedFiles.postValue(loadedFiles.value)52 }53 }54 }55 }56 fun deleteFromApi(id: String, authKey: String): Request {57 return fuelService.deleteFile(id, authKey)58 }59 fun deleteFromLoadedFiles(id: String, loadedFiles: MutableLiveData<MutableList<InfoModel>>) {60 val loadedFilesValue = loadedFiles.value61 if (!loadedFilesValue.isNullOrEmpty()) {62 loadedFilesValue.removeAll { it.id == id }63 loadedFiles.postValue(loadedFilesValue)64 }65 }66}...
Fuel.kt
Source:Fuel.kt
1package com.github.kittinunf.fuel2import com.github.kittinunf.fuel.core.FuelManager3import com.github.kittinunf.fuel.core.Method4import com.github.kittinunf.fuel.core.Parameters5import com.github.kittinunf.fuel.core.Request6import com.github.kittinunf.fuel.core.RequestFactory7import com.github.kittinunf.fuel.core.requests.DownloadRequest8import com.github.kittinunf.fuel.core.requests.UploadRequest9object Fuel : RequestFactory.Convenience by FuelManager.instance {10 var trace = false11 fun trace(function: () -> String) {12 @Suppress("ConstantConditionIf")13 if (trace) println(function())14 }15 fun reset() = FuelManager.instance.reset()16}17fun String.httpGet(parameters: Parameters? = null): Request =18 Fuel.get(this, parameters)19fun RequestFactory.PathStringConvertible.httpGet(parameter: Parameters? = null): Request =20 this.path.httpGet(parameter)21fun String.httpPost(parameters: Parameters? = null): Request =22 Fuel.post(this, parameters)23fun RequestFactory.PathStringConvertible.httpPost(parameters: Parameters? = null): Request =24 this.path.httpPost(parameters)25fun String.httpPut(parameters: Parameters? = null): Request =26 Fuel.put(this, parameters)27fun RequestFactory.PathStringConvertible.httpPut(parameter: Parameters? = null): Request =28 this.path.httpPut(parameter)29fun String.httpPatch(parameters: Parameters? = null): Request =30 Fuel.patch(this, parameters)31fun RequestFactory.PathStringConvertible.httpPatch(parameter: Parameters? = null): Request =32 this.path.httpPatch(parameter)33fun String.httpDelete(parameters: Parameters? = null): Request =34 Fuel.delete(this, parameters)35fun RequestFactory.PathStringConvertible.httpDelete(parameter: Parameters? = null): Request =36 this.path.httpDelete(parameter)37fun String.httpDownload(parameter: Parameters? = null, method: Method = Method.GET): DownloadRequest =38 Fuel.download(this, method, parameter)39fun RequestFactory.PathStringConvertible.httpDownload(parameters: Parameters? = null, method: Method = Method.GET): DownloadRequest =40 this.path.httpDownload(parameters, method)41fun String.httpUpload(parameters: Parameters? = null, method: Method = Method.POST): UploadRequest =42 Fuel.upload(this, method, parameters)43fun RequestFactory.PathStringConvertible.httpUpload(parameters: Parameters? = null, method: Method = Method.POST): UploadRequest =44 this.path.httpUpload(parameters, method)45fun String.httpHead(parameters: Parameters? = null): Request =46 Fuel.head(this, parameters)47fun RequestFactory.PathStringConvertible.httpHead(parameters: Parameters? = null): Request =48 this.path.httpHead(parameters)...
FuelService.kt
Source:FuelService.kt
1package xo.william.pixeldrain.api2import android.util.Log3import com.github.kittinunf.fuel.Fuel4import com.github.kittinunf.fuel.core.*5import com.github.kittinunf.fuel.core.requests.UploadRequest6import com.github.kittinunf.fuel.core.requests.upload7import java.io.InputStream8class FuelService() {9 private val baseUri = "https://pixeldrain.com/api/"10 private val authKeyCookie = "pd_auth_key";11 fun getFileInfoById(id: String): Request {12 val url = "${baseUri}file/${id}/info";13 return Fuel.get(url)14 }15 fun uploadAnonFile(selectedFile: InputStream, fileName: String?): UploadRequest {16 val url = baseUri + "file";17 val setFileName = if (fileName !== null) fileName else "file";18 return Fuel.upload(url, method = Method.POST, parameters = listOf("name" to setFileName))19 .add(BlobDataPart(selectedFile, name = "file", filename = setFileName));20 }21 fun uploadFile(selectedFile: InputStream, fileName: String?, authKey: String): UploadRequest {22 val url = baseUri + "file";23 val setFileName = if (fileName !== null) fileName else "file";24 val authKeyCookie = "${authKeyCookie}=${authKey}";25 return Fuel.upload(url, method = Method.POST, parameters = listOf("name" to setFileName))26 .header(Headers.COOKIE to authKeyCookie).upload()27 .add(BlobDataPart(selectedFile, name = "file", filename = setFileName))28 }29 fun getFiles(authKey: String): Request {30 val url = "${baseUri}/user/files"31 val authKeyCookie = "${authKeyCookie}=${authKey}";32 return Fuel.get(url, parameters = listOf("page" to 0, "limit" to 1000))33 .header(Headers.COOKIE to authKeyCookie)34 }35 fun loginUser(username: String, password: String): Request {36 val url ="${baseUri}/user/login"37 return Fuel.post(url, parameters = listOf("username" to username, "password" to password));38 }39 fun deleteFile(id: String, authKey: String): Request {40 val url ="${baseUri}/file/${id}"41 val authKeyCookie = "${authKeyCookie}=${authKey}";42 return Fuel.delete(url).header(Headers.COOKIE to authKeyCookie)43 }44 fun getFileText(fileUrl: String): Request {45 return Fuel.get(fileUrl);46 }47}...
Request.upload
Using AI Code Generation
1Fuel.upload("/upload", Method.POST) .source { request, url -> File("file.png").inputStream() } .name { request, url -> "file.png" } .progress { readBytes, totalBytes -> println("We are currently reading at ${readBytes} byte!") } .response { request, response, result -> println(response) } .join()2Fuel.upload("/upload", Method.POST) .source { request, url -> File("file.png").inputStream() } .name { request, url -> "file.png" } .progress { readBytes, totalBytes -> println("We are currently reading at ${readBytes} byte!") } .response { request, response, result -> println(response) } .join()3Fuel.upload("/upload", Method.POST) .source { request, url -> File("file.png").inputStream() } .name { request, url -> "file.png" } .progress { readBytes, totalBytes -> println("We are currently reading at ${readBytes} byte!") } .response { request, response, result -> println(response) } .join()4Fuel.upload("/upload",ub.kittinunf. fuel.ce { request, url -> File("file.png").inputStream() } .namore.request, url -> "file.png" } .progress { readBytess totalBytes -> println("We are currently reading at.${readBytes} byte!") } .response { reqUest, pesponse, resultoad println(response) } .join()Request class5} useReqet.upload mthod ofcom.github.kittinunf.fuel.core.requests.Uploadequest class6Fuel.upload("/upload", Method.POST) .source { request, url -> File("file.png").inputStram() } .name { reuest, url -> "file.png" } .progress { readBytes, totalBytes -> println("We are crrntly reading at ${readByte} bye!") } response { request, repnse, reslt -> pintln(response) } .join()7Fuel.upload("/upload", Method.POST)8}9}10}11}12}13}14}
Request.upload
Using AI Code Generation
1}2}3}4}5}6}7}8}9}10}
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!