/* * Copyright (c) 2019-2020. Developed by Hedgecode. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hedgecode.chess.scanner.portal; import java.util.List; 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 implements Scanner { private static final String SETTINGS_FILENAME = "lichess.settings"; @Override protected String getResourceName() { return SETTINGS_FILENAME; } @Override public PGNTournament scanTournament(String tournamentId) throws ScannerException { PGNTournament tournament = new PGNTournament(tournamentId); assignTournamentGames(tournament); return tournament; } @Override 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 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 ScannerException { return scanGame(gameId); } @Override 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 ScannerException { tournament.clearGames(); List pgnGames = split( assignUrl( tournament.id(), null ), PGN_DETECT_REGEX ); if (!pgnGames.isEmpty()) { tournament.setName( StringUtils.match( pgnGames.get(0), getSettings().getTournamentNameRegex() ) ); } for (String pgn : pgnGames) { String gameId = StringUtils.match( pgn, getSettings().getGameIdRegex() ); tournament.addGame( new PGNGame(gameId, pgn) ); } } }