mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-10-30 22:34:02 +01:00 
			
		
		
		
	* #3813 Convert MediaClient to Kotlin - convert * #3813 Convert MediaClient to Kotlin - update tests * #3813 Convert MediaClient to Kotlin - fix List typing * #3813 Convert MediaClient to Kotlin - fix mock injecting
This commit is contained in:
		
							parent
							
								
									e3213aa5bd
								
							
						
					
					
						commit
						422890cac4
					
				
					 7 changed files with 319 additions and 302 deletions
				
			
		|  | @ -8,7 +8,6 @@ import fr.free.nrw.commons.media.MediaClient | |||
| import io.reactivex.Scheduler | ||||
| import io.reactivex.disposables.CompositeDisposable | ||||
| import timber.log.Timber | ||||
| import java.util.* | ||||
| import javax.inject.Inject | ||||
| import javax.inject.Named | ||||
| 
 | ||||
|  | @ -52,11 +51,11 @@ class ContributionBoundaryCallback @Inject constructor( | |||
|      * Fetches contributions using the MediaWiki API | ||||
|      */ | ||||
|     fun fetchContributions() { | ||||
|         if (mediaClient.doesMediaListForUserHaveMorePages(sessionManager.userName).not()) { | ||||
|         if (mediaClient.doesMediaListForUserHaveMorePages(sessionManager.userName!!).not()) { | ||||
|             return | ||||
|         } | ||||
|         compositeDisposable.add( | ||||
|             mediaClient.getMediaListForUser(sessionManager.userName) | ||||
|             mediaClient.getMediaListForUser(sessionManager.userName!!) | ||||
|                 .map { mediaList: List<Media?> -> | ||||
|                     mediaList.map { | ||||
|                         Contribution(it, Contribution.STATE_COMPLETED) | ||||
|  | @ -86,4 +85,4 @@ class ContributionBoundaryCallback @Inject constructor( | |||
|                 } | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import fr.free.nrw.commons.explore.LiveDataConverter | |||
| import fr.free.nrw.commons.explore.PageableDataSource | ||||
| import fr.free.nrw.commons.explore.depictions.LoadFunction | ||||
| import fr.free.nrw.commons.media.MediaClient | ||||
| import fr.free.nrw.commons.media.MediaClient.NO_CAPTION | ||||
| import fr.free.nrw.commons.media.MediaClient.Companion.NO_CAPTION | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| class PageableMediaDataSource @Inject constructor( | ||||
|  |  | |||
|  | @ -1,277 +0,0 @@ | |||
| package fr.free.nrw.commons.media; | ||||
| 
 | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import fr.free.nrw.commons.Media; | ||||
| import fr.free.nrw.commons.utils.CommonsDateUtil; | ||||
| import io.reactivex.Observable; | ||||
| import io.reactivex.Single; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.Date; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Locale; | ||||
| import java.util.Map; | ||||
| import javax.inject.Inject; | ||||
| import javax.inject.Singleton; | ||||
| import org.wikipedia.dataclient.mwapi.MwQueryResponse; | ||||
| import org.wikipedia.wikidata.Entities; | ||||
| import org.wikipedia.wikidata.Entities.Entity; | ||||
| import org.wikipedia.wikidata.Entities.Label; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
| /** | ||||
|  * Media Client to handle custom calls to Commons MediaWiki APIs | ||||
|  */ | ||||
| @Singleton | ||||
| public class MediaClient { | ||||
| 
 | ||||
|     private final MediaInterface mediaInterface; | ||||
|     private final PageMediaInterface pageMediaInterface; | ||||
|     private final MediaDetailInterface mediaDetailInterface; | ||||
| 
 | ||||
|     //OkHttpJsonApiClient used JsonKvStore for this. I don't know why. | ||||
|     private Map<String, Map<String, String>> continuationStore; | ||||
|     private Map<String, Boolean> continuationExists; | ||||
|     public static final String NO_CAPTION = "No caption"; | ||||
|     private static final String NO_DEPICTION = "No depiction"; | ||||
| 
 | ||||
|     @Inject | ||||
|     public MediaClient(MediaInterface mediaInterface, | ||||
|         PageMediaInterface pageMediaInterface, | ||||
|         MediaDetailInterface mediaDetailInterface) { | ||||
|         this.mediaInterface = mediaInterface; | ||||
|         this.pageMediaInterface = pageMediaInterface; | ||||
|         this.mediaDetailInterface = mediaDetailInterface; | ||||
|         this.continuationStore = new HashMap<>(); | ||||
|         this.continuationExists = new HashMap<>(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Checks if a page exists on Commons | ||||
|      * The same method can be used to check for file or talk page | ||||
|      * | ||||
|      * @param title File:Test.jpg or Commons:Deletion_requests/File:Test1.jpeg | ||||
|      */ | ||||
|     public Single<Boolean> checkPageExistsUsingTitle(String title) { | ||||
|         return mediaInterface.checkPageExistsUsingTitle(title) | ||||
|                 .map(mwQueryResponse -> mwQueryResponse | ||||
|                         .query().firstPage().pageId() > 0) | ||||
|                 .singleOrError(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Take the fileSha and returns whether a file with a matching SHA exists or not | ||||
|      * | ||||
|      * @param fileSha SHA of the file to be checked | ||||
|      */ | ||||
|     public Single<Boolean> checkFileExistsUsingSha(String fileSha) { | ||||
|         return mediaInterface.checkFileExistsUsingSha(fileSha) | ||||
|                 .map(mwQueryResponse -> mwQueryResponse | ||||
|                         .query().allImages().size() > 0) | ||||
|                 .singleOrError(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method takes the category as input and returns a list of  Media objects filtered using image generator query | ||||
|      * It uses the generator query API to get the images searched using a query, 10 at a time. | ||||
|      * | ||||
|      * @param category the search category. Must start with "Category:" | ||||
|      * @return | ||||
|      */ | ||||
|     public Single<List<Media>> getMediaListFromCategory(String category) { | ||||
|         return responseToMediaList( | ||||
|                 continuationStore.containsKey("category_" + category) ? | ||||
|                         mediaInterface.getMediaListFromCategory(category, 10, continuationStore.get("category_" + category)) : //if true | ||||
|                         mediaInterface.getMediaListFromCategory(category, 10, Collections.emptyMap()), | ||||
|                 "category_" + category); //if false | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method takes the userName as input and returns a list of  Media objects filtered using | ||||
|      * allimages query It uses the allimages query API to get the images contributed by the userName, | ||||
|      * 10 at a time. | ||||
|      * | ||||
|      * @param userName the username | ||||
|      * @return | ||||
|      */ | ||||
|     public Single<List<Media>> getMediaListForUser(String userName) { | ||||
|         Map<String, String> continuation = | ||||
|             continuationStore.containsKey("user_" + userName) | ||||
|                 ? continuationStore.get("user_" + userName) | ||||
|                 : Collections.emptyMap(); | ||||
|         return responseToMediaList(mediaInterface | ||||
|             .getMediaListForUser(userName, 10, continuation), "user_" + userName); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if media for user has reached the end of the list. | ||||
|      * @param userName | ||||
|      * @return | ||||
|      */ | ||||
|     public boolean doesMediaListForUserHaveMorePages(String userName) { | ||||
|         final String key = "user_" + userName; | ||||
|         if(continuationExists.containsKey(key)) { | ||||
|             return continuationExists.get(key); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method takes a keyword as input and returns a list of  Media objects filtered using image generator query | ||||
|      * It uses the generator query API to get the images searched using a query, 10 at a time. | ||||
|      * | ||||
|      * @param keyword the search keyword | ||||
|      * @param limit | ||||
|      * @param offset | ||||
|      * @return | ||||
|      */ | ||||
|     public Single<MwQueryResponse> getMediaListFromSearch(String keyword, int limit, int offset) { | ||||
|         return mediaInterface.getMediaListFromSearch(keyword, limit, offset); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private Single<List<Media>> responseToMediaList(Observable<MwQueryResponse> response, String key) { | ||||
|         return response.flatMap(mwQueryResponse -> { | ||||
|             if (null == mwQueryResponse | ||||
|                     || null == mwQueryResponse.query() | ||||
|                     || null == mwQueryResponse.query().pages()) { | ||||
|                 return Observable.empty(); | ||||
|             } | ||||
|             if(mwQueryResponse.continuation() != null) { | ||||
|                 continuationStore.put(key, mwQueryResponse.continuation()); | ||||
|                 continuationExists.put(key, true); | ||||
|             } else { | ||||
|                 continuationExists.put(key, false); | ||||
|             } | ||||
|             return Observable.fromIterable(mwQueryResponse.query().pages()); | ||||
|         }) | ||||
|                 .map(Media::from) | ||||
|                 .collect(ArrayList<Media>::new, List::add); | ||||
|     } | ||||
| 
 | ||||
|      /** | ||||
|      * Fetches Media object from the imageInfo API | ||||
|      * | ||||
|      * @param titles the tiles to be searched for. Can be filename or template name | ||||
|      * @return | ||||
|      */ | ||||
|     public Single<Media> getMedia(String titles) { | ||||
|         return mediaInterface.getMedia(titles) | ||||
|                 .flatMap(mwQueryResponse -> { | ||||
|                     if (null == mwQueryResponse | ||||
|                             || null == mwQueryResponse.query() | ||||
|                             || null == mwQueryResponse.query().firstPage()) { | ||||
|                         return Observable.empty(); | ||||
|                     } | ||||
|                     return Observable.just(mwQueryResponse.query().firstPage()); | ||||
|                 }) | ||||
|                 .map(Media::from) | ||||
|                 .single(Media.EMPTY); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The method returns the picture of the day | ||||
|      * | ||||
|      * @return Media object corresponding to the picture of the day | ||||
|      */ | ||||
|     @NonNull | ||||
|     public Single<Media> getPictureOfTheDay() { | ||||
|         String date = CommonsDateUtil.getIso8601DateFormatShort().format(new Date()); | ||||
|         Timber.d("Current date is %s", date); | ||||
|         String template = "Template:Potd/" + date; | ||||
|         return mediaInterface.getMediaWithGenerator(template) | ||||
|                 .flatMap(mwQueryResponse -> { | ||||
|                     if (null == mwQueryResponse | ||||
|                             || null == mwQueryResponse.query() | ||||
|                             || null == mwQueryResponse.query().firstPage()) { | ||||
|                         return Observable.empty(); | ||||
|                     } | ||||
|                     return Observable.just(mwQueryResponse.query().firstPage()); | ||||
|                 }) | ||||
|                 .map(Media::from) | ||||
|                 .single(Media.EMPTY); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     @NonNull | ||||
|     public Single<String> getPageHtml(String title){ | ||||
|         return mediaInterface.getPageHtml(title) | ||||
|                 .filter(MwParseResponse::success) | ||||
|                 .map(MwParseResponse::parse) | ||||
|                 .map(MwParseResult::text) | ||||
|                 .first(""); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * @return  caption for image using wikibaseIdentifier | ||||
|      */ | ||||
|     public Single<String> getCaptionByWikibaseIdentifier(String wikibaseIdentifier) { | ||||
|         return mediaDetailInterface.getEntityForImage(Locale.getDefault().getLanguage(), wikibaseIdentifier) | ||||
|                 .map(mediaDetailResponse -> { | ||||
|                     if (isSuccess(mediaDetailResponse)) { | ||||
|                         for (Entity wikibaseItem : mediaDetailResponse.entities().values()) { | ||||
|                             for (Label label : wikibaseItem.labels().values()) { | ||||
|                                 return label.value(); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     return NO_CAPTION; | ||||
|                 }) | ||||
|                 .singleOrError(); | ||||
|     } | ||||
| 
 | ||||
|     public Single<Boolean> doesPageContainMedia(String title) { | ||||
|         return pageMediaInterface.getMediaList(title) | ||||
|             .map(pageMediaListResponse -> { | ||||
|                 return pageMediaListResponse.getItems().size() > 0; | ||||
|             }).singleOrError(); | ||||
|     } | ||||
| 
 | ||||
|     private boolean isSuccess(Entities response) { | ||||
|         return response != null && response.getSuccess() == 1 && response.entities() != null; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Fetches Structured data from API | ||||
|      * | ||||
|      * @param filename | ||||
|      * @return a map containing caption and depictions (empty string in the map if no caption/depictions) | ||||
|      */ | ||||
|     public Single<Depictions> getDepictions(String filename)  { | ||||
|         return mediaDetailInterface.fetchEntitiesByFileName(Locale.getDefault().getLanguage(), filename) | ||||
|                 .map(entities -> Depictions.from(entities, this)) | ||||
|                 .singleOrError(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets labels for Depictions using Entity Id from MediaWikiAPI | ||||
|      * | ||||
|      * @param entityId  EntityId (Ex: Q81566) of the depict entity | ||||
|      * @return label | ||||
|      */ | ||||
|     public Single<String> getLabelForDepiction(String entityId, String language) { | ||||
|         return mediaDetailInterface.getEntity(entityId) | ||||
|                 .map(entities -> { | ||||
|                     if (isSuccess(entities)) { | ||||
|                         for (Entity entity : entities.entities().values()) { | ||||
|                             final Map<String, Label> languageToLabelMap = entity.labels(); | ||||
|                             if (languageToLabelMap.containsKey(language)) { | ||||
|                                 return languageToLabelMap.get(language).value(); | ||||
|                             } | ||||
|                             for (Label label : languageToLabelMap.values()) { | ||||
|                                 return label.value(); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     throw new RuntimeException("failed getEntities"); | ||||
|                 }); | ||||
|     } | ||||
| 
 | ||||
|     public Single<Entities> getEntities(String entityId) { | ||||
|         return mediaDetailInterface.getEntity(entityId); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										300
									
								
								app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,300 @@ | |||
| package fr.free.nrw.commons.media | ||||
| 
 | ||||
| import fr.free.nrw.commons.Media | ||||
| import fr.free.nrw.commons.media.Depictions.Companion.from | ||||
| import fr.free.nrw.commons.utils.CommonsDateUtil | ||||
| import io.reactivex.Observable | ||||
| import io.reactivex.Single | ||||
| import org.wikipedia.dataclient.mwapi.MwQueryPage | ||||
| import org.wikipedia.dataclient.mwapi.MwQueryResponse | ||||
| import org.wikipedia.wikidata.Entities | ||||
| import timber.log.Timber | ||||
| import java.util.* | ||||
| import javax.inject.Inject | ||||
| import javax.inject.Singleton | ||||
| import kotlin.collections.ArrayList | ||||
| 
 | ||||
| /** | ||||
|  * Media Client to handle custom calls to Commons MediaWiki APIs | ||||
|  */ | ||||
| @Singleton | ||||
| class MediaClient @Inject constructor( | ||||
|     private val mediaInterface: MediaInterface, | ||||
|     private val pageMediaInterface: PageMediaInterface, | ||||
|     private val mediaDetailInterface: MediaDetailInterface | ||||
| ) { | ||||
| 
 | ||||
|     //OkHttpJsonApiClient used JsonKvStore for this. I don't know why. | ||||
|     private val continuationStore: MutableMap<String, Map<String, String>?> | ||||
|     private val continuationExists: MutableMap<String, Boolean> | ||||
| 
 | ||||
|     /** | ||||
|      * Checks if a page exists on Commons | ||||
|      * The same method can be used to check for file or talk page | ||||
|      * | ||||
|      * @param title File:Test.jpg or Commons:Deletion_requests/File:Test1.jpeg | ||||
|      */ | ||||
|     fun checkPageExistsUsingTitle(title: String?): Single<Boolean> { | ||||
|         return mediaInterface.checkPageExistsUsingTitle(title) | ||||
|             .map { mwQueryResponse: MwQueryResponse -> | ||||
|                 mwQueryResponse | ||||
|                     .query()!!.firstPage()!!.pageId() > 0 | ||||
|             } | ||||
|             .singleOrError() | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Take the fileSha and returns whether a file with a matching SHA exists or not | ||||
|      * | ||||
|      * @param fileSha SHA of the file to be checked | ||||
|      */ | ||||
|     fun checkFileExistsUsingSha(fileSha: String?): Single<Boolean> { | ||||
|         return mediaInterface.checkFileExistsUsingSha(fileSha) | ||||
|             .map { mwQueryResponse: MwQueryResponse -> | ||||
|                 mwQueryResponse | ||||
|                     .query()!!.allImages().size > 0 | ||||
|             } | ||||
|             .singleOrError() | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method takes the category as input and returns a list of  Media objects filtered using image generator query | ||||
|      * It uses the generator query API to get the images searched using a query, 10 at a time. | ||||
|      * | ||||
|      * @param category the search category. Must start with "Category:" | ||||
|      * @return | ||||
|      */ | ||||
|     fun getMediaListFromCategory(category: String): Single<List<Media>> { | ||||
|         return responseToMediaList( | ||||
|             if (continuationStore.containsKey("category_$category")) mediaInterface.getMediaListFromCategory( | ||||
|                 category, | ||||
|                 10, | ||||
|                 continuationStore["category_$category"] | ||||
|             ) else  //if true | ||||
|                 mediaInterface.getMediaListFromCategory( | ||||
|                     category, | ||||
|                     10, | ||||
|                     emptyMap() | ||||
|                 ), | ||||
|             "category_$category" | ||||
|         ) //if false | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method takes the userName as input and returns a list of  Media objects filtered using | ||||
|      * allimages query It uses the allimages query API to get the images contributed by the userName, | ||||
|      * 10 at a time. | ||||
|      * | ||||
|      * @param userName the username | ||||
|      * @return | ||||
|      */ | ||||
|     fun getMediaListForUser(userName: String): Single<List<Media>> { | ||||
|         val continuation = | ||||
|             if (continuationStore.containsKey("user_$userName")) continuationStore["user_$userName"] else emptyMap() | ||||
|         return responseToMediaList( | ||||
|             mediaInterface | ||||
|                 .getMediaListForUser(userName, 10, continuation), "user_$userName" | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if media for user has reached the end of the list. | ||||
|      * @param userName | ||||
|      * @return | ||||
|      */ | ||||
|     fun doesMediaListForUserHaveMorePages(userName: String): Boolean { | ||||
|         val key = "user_$userName" | ||||
|         return if (continuationExists.containsKey(key)) { | ||||
|             continuationExists[key]!! | ||||
|         } else true | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method takes a keyword as input and returns a list of  Media objects filtered using image generator query | ||||
|      * It uses the generator query API to get the images searched using a query, 10 at a time. | ||||
|      * | ||||
|      * @param keyword the search keyword | ||||
|      * @param limit | ||||
|      * @param offset | ||||
|      * @return | ||||
|      */ | ||||
|     fun getMediaListFromSearch( | ||||
|         keyword: String?, | ||||
|         limit: Int, | ||||
|         offset: Int | ||||
|     ): Single<MwQueryResponse> { | ||||
|         return mediaInterface.getMediaListFromSearch(keyword, limit, offset) | ||||
|     } | ||||
| 
 | ||||
|     private fun responseToMediaList( | ||||
|         response: Observable<MwQueryResponse>, | ||||
|         key: String | ||||
|     ): Single<List<Media>> { | ||||
|         return response.flatMap { mwQueryResponse: MwQueryResponse? -> | ||||
|             if (null == mwQueryResponse || null == mwQueryResponse.query() || null == mwQueryResponse.query()!! | ||||
|                     .pages() | ||||
|             ) { | ||||
|                 return@flatMap Observable.empty<MwQueryPage>() | ||||
|             } | ||||
|             if (mwQueryResponse.continuation() != null) { | ||||
|                 continuationStore[key] = mwQueryResponse.continuation() | ||||
|                 continuationExists[key] = true | ||||
|             } else { | ||||
|                 continuationExists[key] = false | ||||
|             } | ||||
|             Observable.fromIterable(mwQueryResponse.query()!!.pages()) | ||||
|         } | ||||
|             .map { page: MwQueryPage? -> Media.from(page) } | ||||
|             .collect( | ||||
|                 { ArrayList() } | ||||
|             ) { obj: MutableList<Media>, e: Media -> | ||||
|                 obj.add( | ||||
|                     e | ||||
|                 ) | ||||
|             }.map { it.toList() } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Fetches Media object from the imageInfo API | ||||
|      * | ||||
|      * @param titles the tiles to be searched for. Can be filename or template name | ||||
|      * @return | ||||
|      */ | ||||
|     fun getMedia(titles: String?): Single<Media> { | ||||
|         return mediaInterface.getMedia(titles) | ||||
|             .flatMap { mwQueryResponse: MwQueryResponse? -> | ||||
|                 if (null == mwQueryResponse || null == mwQueryResponse.query() || null == mwQueryResponse.query()!! | ||||
|                         .firstPage() | ||||
|                 ) { | ||||
|                     return@flatMap Observable.empty<MwQueryPage>() | ||||
|                 } | ||||
|                 Observable.just(mwQueryResponse.query()!!.firstPage()) | ||||
|             } | ||||
|             .map { page: MwQueryPage? -> Media.from(page) } | ||||
|             .single(Media.EMPTY) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The method returns the picture of the day | ||||
|      * | ||||
|      * @return Media object corresponding to the picture of the day | ||||
|      */ | ||||
|     val pictureOfTheDay: Single<Media> | ||||
|         get() { | ||||
|             val date = | ||||
|                 CommonsDateUtil.getIso8601DateFormatShort().format(Date()) | ||||
|             Timber.d("Current date is %s", date) | ||||
|             val template = "Template:Potd/$date" | ||||
|             return mediaInterface.getMediaWithGenerator(template) | ||||
|                 .flatMap { mwQueryResponse: MwQueryResponse? -> | ||||
|                     if (null == mwQueryResponse || null == mwQueryResponse.query() || null == mwQueryResponse.query()!! | ||||
|                             .firstPage() | ||||
|                     ) { | ||||
|                         return@flatMap Observable.empty<MwQueryPage>() | ||||
|                     } | ||||
|                     Observable.just(mwQueryResponse.query()!!.firstPage()) | ||||
|                 } | ||||
|                 .map { page: MwQueryPage? -> Media.from(page) } | ||||
|                 .single(Media.EMPTY) | ||||
|         } | ||||
| 
 | ||||
|     fun getPageHtml(title: String?): Single<String> { | ||||
|         return mediaInterface.getPageHtml(title) | ||||
|             .filter { obj: MwParseResponse -> obj.success() } | ||||
|             .map { obj: MwParseResponse -> obj.parse() } | ||||
|             .map { obj: MwParseResult? -> obj!!.text() } | ||||
|             .first("") | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return  caption for image using wikibaseIdentifier | ||||
|      */ | ||||
|     fun getCaptionByWikibaseIdentifier(wikibaseIdentifier: String?): Single<String> { | ||||
|         return mediaDetailInterface.getEntityForImage( | ||||
|             Locale.getDefault().language, | ||||
|             wikibaseIdentifier | ||||
|         ) | ||||
|             .map { mediaDetailResponse: Entities -> | ||||
|                 if (isSuccess(mediaDetailResponse)) { | ||||
|                     for (wikibaseItem in mediaDetailResponse.entities().values) { | ||||
|                         for (label in wikibaseItem.labels().values) { | ||||
|                             return@map label.value() | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 NO_CAPTION | ||||
|             } | ||||
|             .singleOrError() | ||||
|     } | ||||
| 
 | ||||
|     fun doesPageContainMedia(title: String?): Single<Boolean> { | ||||
|         return pageMediaInterface.getMediaList(title) | ||||
|             .map { it.items.isNotEmpty() } | ||||
|     } | ||||
| 
 | ||||
|     private fun isSuccess(response: Entities?): Boolean { | ||||
|         return response != null && response.success == 1 && response.entities() != null | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Fetches Structured data from API | ||||
|      * | ||||
|      * @param filename | ||||
|      * @return a map containing caption and depictions (empty string in the map if no caption/depictions) | ||||
|      */ | ||||
|     fun getDepictions(filename: String?): Single<Depictions> { | ||||
|         return mediaDetailInterface.fetchEntitiesByFileName( | ||||
|             Locale.getDefault().language, filename | ||||
|         ) | ||||
|             .map { entities: Entities? -> | ||||
|                 from( | ||||
|                     entities!!, | ||||
|                     this | ||||
|                 ) | ||||
|             } | ||||
|             .singleOrError() | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets labels for Depictions using Entity Id from MediaWikiAPI | ||||
|      * | ||||
|      * @param entityId  EntityId (Ex: Q81566) of the depict entity | ||||
|      * @return label | ||||
|      */ | ||||
|     fun getLabelForDepiction( | ||||
|         entityId: String?, | ||||
|         language: String | ||||
|     ): Single<String> { | ||||
|         return mediaDetailInterface.getEntity(entityId) | ||||
|             .map { entities: Entities -> | ||||
|                 if (isSuccess(entities)) { | ||||
|                     for (entity in entities.entities().values) { | ||||
|                         val languageToLabelMap = | ||||
|                             entity.labels() | ||||
|                         if (languageToLabelMap.containsKey(language)) { | ||||
|                             return@map languageToLabelMap[language]!!.value() | ||||
|                         } | ||||
|                         for (label in languageToLabelMap.values) { | ||||
|                             return@map label.value() | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 throw RuntimeException("failed getEntities") | ||||
|             } | ||||
|     } | ||||
| 
 | ||||
|     fun getEntities(entityId: String?): Single<Entities> { | ||||
|         return mediaDetailInterface.getEntity(entityId) | ||||
|     } | ||||
| 
 | ||||
|     companion object { | ||||
|         const val NO_CAPTION = "No caption" | ||||
|         private const val NO_DEPICTION = "No depiction" | ||||
|     } | ||||
| 
 | ||||
|     init { | ||||
|         continuationStore = | ||||
|             HashMap() | ||||
|         continuationExists = HashMap() | ||||
|     } | ||||
| } | ||||
|  | @ -1,7 +1,7 @@ | |||
| package fr.free.nrw.commons.media | ||||
| 
 | ||||
| import fr.free.nrw.commons.media.model.PageMediaListResponse | ||||
| import io.reactivex.Observable | ||||
| import io.reactivex.Single | ||||
| import retrofit2.http.GET | ||||
| import retrofit2.http.Path | ||||
| 
 | ||||
|  | @ -15,5 +15,5 @@ interface PageMediaInterface { | |||
|      * @param title the title of the page | ||||
|      */ | ||||
|     @GET("api/rest_v1/page/media-list/{title}") | ||||
|     fun getMediaList(@Path("title") title: String?): Observable<PageMediaListResponse?>? | ||||
| } | ||||
|     fun getMediaList(@Path("title") title: String?): Single<PageMediaListResponse> | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Seán Mac Gillicuddy
						Seán Mac Gillicuddy