[LIB-13] Functional for working with strings moved to StringUtils
[chesshog-scanner.git] / src / main / java / org / hedgecode / chess / scanner / portal / LiChessScanner.java
index 134180e..820e513 100644 (file)
 package org.hedgecode.chess.scanner.portal;
 
 import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
-import org.hedgecode.chess.scanner.ChessHogScannerException;
+import org.apache.commons.text.StringEscapeUtils;
+
+import org.hedgecode.chess.scanner.Scanner;
+import org.hedgecode.chess.scanner.ScannerException;
+import org.hedgecode.chess.scanner.StringUtils;
 import org.hedgecode.chess.scanner.entity.PGNGame;
 import org.hedgecode.chess.scanner.entity.PGNTournament;
+import org.hedgecode.chess.scanner.format.lichess.Format;
+import org.hedgecode.chess.scanner.format.lichess.GameFormat;
+
+import static org.hedgecode.chess.scanner.format.PGNConstants.*;
 
 /**
  * LiChessScanner
  *
  * @author Dmitry Samoshin aka gotty
  */
-public class LiChessScanner extends AbstractSettingsScanner {
+public class LiChessScanner extends AbstractSettingsScanner implements Scanner {
 
     private static final String SETTINGS_FILENAME = "lichess.settings";
 
-    private static final String TOURNAMENT_GAMES_SPLIT_REGEX = "\\[Event \"[^\"]+\"\\]";
-    private static final String TOURNAMENT_NAME_REGEX = "\\[Event \"([^\"]+)\"\\]";
-    private static final String GAME_ID_REGEX = "\\[Site \"https://lichess.org/([^\"]+)\"\\]";
-
     @Override
     protected String getResourceName() {
         return SETTINGS_FILENAME;
     }
 
     @Override
-    public PGNTournament scanTournament(String tournamentId) throws ChessHogScannerException {
+    public PGNTournament scanTournament(String tournamentId) throws ScannerException {
         PGNTournament tournament = new PGNTournament(tournamentId);
         assignTournamentGames(tournament);
         return tournament;
     }
 
     @Override
-    public PGNTournament findTournament(String tournamentName) throws ChessHogScannerException {
-        throw new ChessHogScannerException(
+    public PGNTournament findTournament(String tournamentName) throws ScannerException {
+        throw new ScannerException(
                 "Lichess does not support searching for a tournament by name!"
         );
     }
 
     @Override
-    public PGNGame scanGame(String gameId) throws ChessHogScannerException {
+    public PGNGame scanGame(String gameId) throws ScannerException {
         String pgn = request(
                 assignUrl(gameId)
         );
+        if (!StringUtils.isPgn(pgn)) {
+            throw new ScannerException(
+                    String.format("Failed to get PGN for requesting game ID: %s", gameId)
+            );
+        }
         return new PGNGame(
                 gameId, pgn
         );
     }
 
     @Override
-    public PGNGame scanGame(String gameId, String tournamentId) throws ChessHogScannerException {
+    public PGNGame scanGame(String gameId, String tournamentId) throws ScannerException {
         return scanGame(gameId);
     }
 
     @Override
-    public PGNGame scanUrl(String gameUrl) throws ChessHogScannerException {
-        return null;
+    public PGNGame scanUrl(String gameUrl) throws ScannerException {
+        String gamePage = request(gameUrl);
+        String pgn = StringUtils.match(
+                gamePage,
+                getSettings().getGameUrlRegex()
+        );
+        if (pgn == null) {
+            pgn = StringUtils.match(
+                    gamePage,
+                    getSettings().getGameJsonUrlRegex()
+            );
+            if (pgn == null) {
+                throw new ScannerException(
+                        String.format("Failed to get source data for requesting URL: %s", gameUrl)
+                );
+            }
+            GameFormat gameFormat = Format.formatGame(pgn);
+            return new PGNGame(
+                    gameFormat.id(),
+                    gameFormat.pgn()
+            );
+        } else {
+            pgn = StringEscapeUtils.unescapeHtml4(pgn);
+            if (!StringUtils.isPgn(pgn)) {
+                throw new ScannerException(
+                        String.format("Failed to get PGN for requesting URL: %s", gameUrl)
+                );
+            }
+            return new PGNGame(
+                    StringUtils.match(
+                            pgn,
+                            getSettings().getGameIdRegex()
+                    ),
+                    pgn
+            );
+        }
     }
 
-    private void assignTournamentGames(PGNTournament tournament) throws ChessHogScannerException {
+    private void assignTournamentGames(PGNTournament tournament) throws ScannerException {
         tournament.clearGames();
         List<String> pgnGames = split(
                 assignUrl(
                         tournament.id(),
                         null
                 ),
-                TOURNAMENT_GAMES_SPLIT_REGEX
+                PGN_DETECT_REGEX
         );
 
         if (!pgnGames.isEmpty()) {
             tournament.setName(
-                    find(TOURNAMENT_NAME_REGEX, pgnGames.get(0))
+                    StringUtils.match(
+                            pgnGames.get(0),
+                            getSettings().getTournamentNameRegex()
+                    )
             );
         }
 
         for (String pgn : pgnGames) {
-            String gameId = find(GAME_ID_REGEX, pgn);
+            String gameId = StringUtils.match(
+                    pgn,
+                    getSettings().getGameIdRegex()
+            );
             tournament.addGame(
                     new PGNGame(gameId, pgn)
             );
         }
     }
 
-    private String find(String regex, String pgn) {
-        Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
-        Matcher matcher = pattern.matcher(pgn);
-        if (matcher.find()) {
-            return matcher.group(1);
-        }
-        return null;
-    }
-
 }