1
1
package fr .free .nrw .commons .review ;
2
2
3
+
4
+ import androidx .core .util .Pair ;
5
+
3
6
import org .wikipedia .dataclient .mwapi .MwQueryPage ;
4
7
import org .wikipedia .dataclient .mwapi .RecentChange ;
8
+ import org .wikipedia .util .DateUtil ;
5
9
10
+ import java .util .Collections ;
11
+ import java .util .Date ;
6
12
import java .util .List ;
7
13
import java .util .Random ;
8
14
9
- import javax .annotation .Nullable ;
10
15
import javax .inject .Inject ;
11
16
import javax .inject .Singleton ;
12
17
13
- import androidx .core .util .Pair ;
14
18
import fr .free .nrw .commons .Media ;
15
19
import fr .free .nrw .commons .mwapi .MediaWikiApi ;
16
20
import fr .free .nrw .commons .mwapi .OkHttpJsonApiClient ;
17
- import io .reactivex .Single ;
21
+ import io .reactivex .Maybe ;
22
+ import io .reactivex .Observable ;
18
23
19
24
@ Singleton
20
25
public class ReviewHelper {
@@ -24,16 +29,29 @@ public class ReviewHelper {
24
29
25
30
private final OkHttpJsonApiClient okHttpJsonApiClient ;
26
31
private final MediaWikiApi mediaWikiApi ;
32
+ private final ReviewInterface reviewInterface ;
27
33
28
34
@ Inject
29
- public ReviewHelper (OkHttpJsonApiClient okHttpJsonApiClient , MediaWikiApi mediaWikiApi ) {
35
+ public ReviewHelper (OkHttpJsonApiClient okHttpJsonApiClient ,
36
+ MediaWikiApi mediaWikiApi ,
37
+ ReviewInterface reviewInterface ) {
30
38
this .okHttpJsonApiClient = okHttpJsonApiClient ;
31
39
this .mediaWikiApi = mediaWikiApi ;
40
+ this .reviewInterface = reviewInterface ;
32
41
}
33
42
34
- Single <Media > getRandomMedia () {
35
- return getRandomFileChange ()
36
- .flatMap (fileName -> okHttpJsonApiClient .getMedia (fileName , false ));
43
+ private Observable <List <RecentChange >> getRecentChanges () {
44
+ final int RANDOM_SECONDS = 60 * 60 * 24 * 30 ;
45
+ Random r = new Random ();
46
+ Date now = new Date ();
47
+ Date startDate = new Date (now .getTime () - r .nextInt (RANDOM_SECONDS ) * 1000L );
48
+
49
+ String rcStart = DateUtil .iso8601DateFormat (startDate );
50
+ return reviewInterface .getRecentChanges (rcStart ).map (mwQueryResponse -> mwQueryResponse .query ().getRecentChanges ())
51
+ .map (recentChanges -> {
52
+ Collections .shuffle (recentChanges );
53
+ return recentChanges ;
54
+ });
37
55
}
38
56
39
57
/**
@@ -43,57 +61,40 @@ Single<Media> getRandomMedia() {
43
61
* - Checks if the file is nominated for deletion
44
62
* - Retries upto 5 times for getting a file which is not nominated for deletion
45
63
*
46
- * @return
64
+ * @return Random file change
47
65
*/
48
- private Single <String > getRandomFileChange () {
49
- return okHttpJsonApiClient .getRecentFileChanges ()
50
- .map (this ::findImageInRecentChanges )
51
- .flatMap (title -> mediaWikiApi .pageExists ("Commons:Deletion_requests/" + title )
52
- .map (pageExists -> new Pair <>(title , pageExists )))
53
- .map ((Pair <String , Boolean > pair ) -> {
54
- if (!pair .second ) {
55
- return pair .first ;
66
+ public Maybe <Media > getRandomMedia () {
67
+ return getRecentChanges ()
68
+ .flatMapIterable (changes -> changes )
69
+ .filter (this ::isChangeReviewable )
70
+ .flatMapSingle (change -> mediaWikiApi .pageExists ("Commons:Deletion_requests/" + change .getTitle ())
71
+ .map (exists -> new Pair <>(change .getTitle (), exists )))
72
+ .flatMapSingle (fileNamePair -> {
73
+ if (fileNamePair .second != null && !fileNamePair .second ) {
74
+ return okHttpJsonApiClient .getMedia (fileNamePair .first , false );
56
75
}
57
- throw new Exception ("Already nominated for deletion" );
58
- }).retry (MAX_RANDOM_TRIES );
76
+ return null ;
77
+ })
78
+ .filter (media -> media != null )
79
+ .firstElement ();
59
80
}
60
81
61
- Single <MwQueryPage .Revision > getFirstRevisionOfFile (String fileName ) {
62
- return okHttpJsonApiClient .getFirstRevisionOfFile (fileName );
82
+ Observable <MwQueryPage .Revision > getFirstRevisionOfFile (String filename ) {
83
+ return reviewInterface .getFirstRevisionOfFile (filename )
84
+ .map (response -> response .query ().firstPage ().revisions ().get (0 ));
63
85
}
64
86
65
- @ Nullable
66
- private String findImageInRecentChanges (List <RecentChange > recentChanges ) {
67
- String imageTitle ;
68
- Random r = new Random ();
69
- int count = recentChanges .size ();
70
- // Build a range array
71
- int [] randomIndexes = new int [count ];
72
- for (int i = 0 ; i < count ; i ++) {
73
- randomIndexes [i ] = i ;
74
- }
75
- // Then shuffle it
76
- for (int i = 0 ; i < count ; i ++) {
77
- int swapIndex = r .nextInt (count );
78
- int temp = randomIndexes [i ];
79
- randomIndexes [i ] = randomIndexes [swapIndex ];
80
- randomIndexes [swapIndex ] = temp ;
87
+ private boolean isChangeReviewable (RecentChange recentChange ) {
88
+ if (recentChange .getType ().equals ("log" ) && !(recentChange .getOldRevisionId () == 0 )) {
89
+ return false ;
81
90
}
82
- for (int i = 0 ; i < count ; i ++) {
83
- int randomIndex = randomIndexes [i ];
84
- RecentChange recentChange = recentChanges .get (randomIndex );
85
- if (recentChange .getType ().equals ("log" ) && !(recentChange .getOldRevisionId () == 0 )) {
86
- // For log entries, we only want ones where old_revid is zero, indicating a new file
87
- continue ;
88
- }
89
- imageTitle = recentChange .getTitle ();
90
91
91
- for (String imageExtension : imageExtensions ) {
92
- if (imageTitle .toLowerCase ().endsWith (imageExtension )) {
93
- return imageTitle ;
94
- }
92
+ for (String extension : imageExtensions ) {
93
+ if (recentChange .getTitle ().endsWith (extension )) {
94
+ return true ;
95
95
}
96
96
}
97
- return null ;
97
+
98
+ return false ;
98
99
}
99
100
}
0 commit comments