feat: adds skeleton for gb64 scraper

This commit is contained in:
mikael.lantz 2021-01-15 16:34:20 +01:00
parent 54ab582c20
commit 46f97d96be
4 changed files with 553 additions and 2 deletions

View File

@ -0,0 +1,389 @@
package se.lantz.gui.scraper;
import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.net.URISyntaxException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.HyperlinkEvent;
import se.lantz.manager.ScraperManager;
import se.lantz.model.data.ScraperFields;
import se.lantz.util.ExceptionHandler;
public class Gb64comOptionsPanel extends JPanel
{
private JEditorPane infoEditorPane;
private JTextField urlTextField;
private JPanel fieldsPanel;
private JLabel fieldsInfoLabel;
private JCheckBox titleCheckBox;
private JCheckBox authorCheckBox;
private JCheckBox yearCheckBox;
private JCheckBox gameCheckBox;
private JCheckBox coverCheckBox;
private JCheckBox screensCheckBox;
private ScraperManager scraper;
private JButton connectButton;
private JLabel connectionStatusLabel;
private Cursor waitCursor = new Cursor(Cursor.WAIT_CURSOR);
private Cursor defaultCursor = new Cursor(Cursor.DEFAULT_CURSOR);
private JButton okButton;
private JCheckBox genreCheckBox;
private JCheckBox composerCheckBox;
public Gb64comOptionsPanel(ScraperManager scraper, JButton okButton)
{
this.scraper = scraper;
this.okButton = okButton;
GridBagLayout gridBagLayout = new GridBagLayout();
setLayout(gridBagLayout);
GridBagConstraints gbc_infoLabel = new GridBagConstraints();
gbc_infoLabel.gridwidth = 2;
gbc_infoLabel.weightx = 1.0;
gbc_infoLabel.fill = GridBagConstraints.HORIZONTAL;
gbc_infoLabel.insets = new Insets(10, 10, 5, 10);
gbc_infoLabel.gridx = 0;
gbc_infoLabel.gridy = 0;
add(getInfoEditorPane(), gbc_infoLabel);
GridBagConstraints gbc_urlTextField = new GridBagConstraints();
gbc_urlTextField.weightx = 1.0;
gbc_urlTextField.insets = new Insets(0, 10, 10, 5);
gbc_urlTextField.fill = GridBagConstraints.HORIZONTAL;
gbc_urlTextField.gridx = 0;
gbc_urlTextField.gridy = 1;
add(getUrlTextField(), gbc_urlTextField);
GridBagConstraints gbc_connectButton = new GridBagConstraints();
gbc_connectButton.anchor = GridBagConstraints.NORTHWEST;
gbc_connectButton.insets = new Insets(0, 0, 10, 10);
gbc_connectButton.gridx = 1;
gbc_connectButton.gridy = 1;
add(getConnectButton(), gbc_connectButton);
GridBagConstraints gbc_connectionStatusLabel = new GridBagConstraints();
gbc_connectionStatusLabel.gridwidth = 2;
gbc_connectionStatusLabel.insets = new Insets(0, 10, 10, 5);
gbc_connectionStatusLabel.gridx = 0;
gbc_connectionStatusLabel.gridy = 2;
add(getConnectionStatusLabel(), gbc_connectionStatusLabel);
GridBagConstraints gbc_fieldsPanel = new GridBagConstraints();
gbc_fieldsPanel.insets = new Insets(0, 0, 10, 0);
gbc_fieldsPanel.gridwidth = 2;
gbc_fieldsPanel.anchor = GridBagConstraints.NORTH;
gbc_fieldsPanel.weighty = 1.0;
gbc_fieldsPanel.weightx = 1.0;
gbc_fieldsPanel.gridx = 0;
gbc_fieldsPanel.gridy = 3;
add(getFieldsPanel(), gbc_fieldsPanel);
okButton.setEnabled(false);
}
private JEditorPane getInfoEditorPane()
{
if (infoEditorPane == null)
{
String info = "<html>To scrape information from gb64.com you need to specify the URL for a specific game." +
"<ol><li>Go to <a href='http://www.gb64.com/search.php?h=0'>http:/www.gb64.com/</a> and search for the game you want to<br>scrape information for.</li>" +
"<li>Select the game. Enter the GB64-ID in the URL below, or just copy the <br>URL from the browser" +
"(Example: http://www.gb64.com/game.php?id=398)</li></ol></html>";
infoEditorPane = new JEditorPane("text/html", info);
infoEditorPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
infoEditorPane.setFont(UIManager.getDefaults().getFont("Label.font"));
infoEditorPane.setEditable(false);
infoEditorPane.setOpaque(false);
infoEditorPane.addHyperlinkListener((hle) -> {
if (HyperlinkEvent.EventType.ACTIVATED.equals(hle.getEventType()) && Desktop.isDesktopSupported() &&
Desktop.getDesktop().isSupported(Desktop.Action.BROWSE))
{
try
{
Desktop.getDesktop().browse(hle.getURL().toURI());
}
catch (IOException | URISyntaxException e)
{
ExceptionHandler.handleException(e, "Could not open default browser");
}
}
});
}
return infoEditorPane;
}
JTextField getUrlTextField()
{
if (urlTextField == null)
{
urlTextField = new JTextField();
urlTextField.setText("http://www.gb64.com/game.php?id=");
urlTextField.addKeyListener(new KeyAdapter()
{
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
getConnectButton().doClick();
}
}
});
}
return urlTextField;
}
private JPanel getFieldsPanel()
{
if (fieldsPanel == null)
{
fieldsPanel = new JPanel();
GridBagLayout gbl_fieldsPanel = new GridBagLayout();
fieldsPanel.setLayout(gbl_fieldsPanel);
GridBagConstraints gbc_fieldsInfoLabel = new GridBagConstraints();
gbc_fieldsInfoLabel.gridwidth = 3;
gbc_fieldsInfoLabel.weightx = 1.0;
gbc_fieldsInfoLabel.insets = new Insets(0, 0, 5, 0);
gbc_fieldsInfoLabel.anchor = GridBagConstraints.NORTH;
gbc_fieldsInfoLabel.gridx = 0;
gbc_fieldsInfoLabel.gridy = 0;
fieldsPanel.add(getFieldsInfoLabel(), gbc_fieldsInfoLabel);
GridBagConstraints gbc_titleCheckBox = new GridBagConstraints();
gbc_titleCheckBox.insets = new Insets(0, 0, 5, 5);
gbc_titleCheckBox.anchor = GridBagConstraints.WEST;
gbc_titleCheckBox.gridx = 0;
gbc_titleCheckBox.gridy = 1;
fieldsPanel.add(getTitleCheckBox(), gbc_titleCheckBox);
GridBagConstraints gbc_authorCheckBox = new GridBagConstraints();
gbc_authorCheckBox.insets = new Insets(0, 0, 5, 5);
gbc_authorCheckBox.anchor = GridBagConstraints.WEST;
gbc_authorCheckBox.gridx = 0;
gbc_authorCheckBox.gridy = 2;
fieldsPanel.add(getAuthorCheckBox(), gbc_authorCheckBox);
GridBagConstraints gbc_composerCheckBox = new GridBagConstraints();
gbc_composerCheckBox.anchor = GridBagConstraints.WEST;
gbc_composerCheckBox.insets = new Insets(0, 0, 5, 5);
gbc_composerCheckBox.gridx = 1;
gbc_composerCheckBox.gridy = 2;
fieldsPanel.add(getComposerCheckBox(), gbc_composerCheckBox);
GridBagConstraints gbc_coverCheckBox = new GridBagConstraints();
gbc_coverCheckBox.anchor = GridBagConstraints.WEST;
gbc_coverCheckBox.insets = new Insets(0, 0, 5, 5);
gbc_coverCheckBox.gridx = 1;
gbc_coverCheckBox.gridy = 3;
fieldsPanel.add(getCoverCheckBox(), gbc_coverCheckBox);
GridBagConstraints gbc_yearCheckBox = new GridBagConstraints();
gbc_yearCheckBox.insets = new Insets(0, 0, 5, 5);
gbc_yearCheckBox.anchor = GridBagConstraints.WEST;
gbc_yearCheckBox.gridx = 0;
gbc_yearCheckBox.gridy = 3;
fieldsPanel.add(getYearCheckBox(), gbc_yearCheckBox);
GridBagConstraints gbc_gameCheckBox = new GridBagConstraints();
gbc_gameCheckBox.insets = new Insets(0, 0, 5, 5);
gbc_gameCheckBox.anchor = GridBagConstraints.WEST;
gbc_gameCheckBox.gridx = 1;
gbc_gameCheckBox.gridy = 1;
fieldsPanel.add(getGameCheckBox(), gbc_gameCheckBox);
GridBagConstraints gbc_genreCheckBox = new GridBagConstraints();
gbc_genreCheckBox.insets = new Insets(0, 0, 0, 5);
gbc_genreCheckBox.anchor = GridBagConstraints.WEST;
gbc_genreCheckBox.gridx = 0;
gbc_genreCheckBox.gridy = 4;
fieldsPanel.add(getGenreCheckBox(), gbc_genreCheckBox);
GridBagConstraints gbc_screensCheckBox = new GridBagConstraints();
gbc_screensCheckBox.insets = new Insets(0, 0, 0, 5);
gbc_screensCheckBox.anchor = GridBagConstraints.WEST;
gbc_screensCheckBox.gridx = 1;
gbc_screensCheckBox.gridy = 4;
fieldsPanel.add(getScreensCheckBox(), gbc_screensCheckBox);
}
return fieldsPanel;
}
private JLabel getFieldsInfoLabel()
{
if (fieldsInfoLabel == null)
{
fieldsInfoLabel = new JLabel("Select fields to scrape:");
}
return fieldsInfoLabel;
}
private JCheckBox getTitleCheckBox()
{
if (titleCheckBox == null)
{
titleCheckBox = new JCheckBox("Title");
titleCheckBox.setSelected(true);
titleCheckBox.setEnabled(false);
}
return titleCheckBox;
}
private JCheckBox getAuthorCheckBox()
{
if (authorCheckBox == null)
{
authorCheckBox = new JCheckBox("Author");
authorCheckBox.setSelected(true);
authorCheckBox.setEnabled(false);
}
return authorCheckBox;
}
private JCheckBox getYearCheckBox()
{
if (yearCheckBox == null)
{
yearCheckBox = new JCheckBox("Year");
yearCheckBox.setSelected(true);
yearCheckBox.setEnabled(false);
}
return yearCheckBox;
}
private JCheckBox getGameCheckBox()
{
if (gameCheckBox == null)
{
gameCheckBox = new JCheckBox("Game file");
gameCheckBox.setSelected(true);
gameCheckBox.setEnabled(false);
}
return gameCheckBox;
}
private JCheckBox getCoverCheckBox()
{
if (coverCheckBox == null)
{
coverCheckBox = new JCheckBox("Cover");
coverCheckBox.setSelected(true);
coverCheckBox.setEnabled(false);
}
return coverCheckBox;
}
private JCheckBox getScreensCheckBox()
{
if (screensCheckBox == null)
{
screensCheckBox = new JCheckBox("Screenshots");
screensCheckBox.setSelected(true);
screensCheckBox.setEnabled(false);
}
return screensCheckBox;
}
private void enableCheckBoxes(boolean enable)
{
titleCheckBox.setEnabled(enable);
authorCheckBox.setEnabled(enable);
yearCheckBox.setEnabled(enable);
gameCheckBox.setEnabled(enable);
coverCheckBox.setEnabled(enable);
screensCheckBox.setEnabled(enable);
genreCheckBox.setEnabled(enable);
composerCheckBox.setEnabled(enable);
}
public ScraperFields getScraperFields()
{
ScraperFields returnValue = new ScraperFields();
returnValue.setTitle(titleCheckBox.isSelected());
returnValue.setAuthor(authorCheckBox.isSelected());
returnValue.setYear(yearCheckBox.isSelected());
returnValue.setGenre(genreCheckBox.isSelected());
//No description available
returnValue.setDescription(false);
returnValue.setCover(coverCheckBox.isSelected());
returnValue.setScreenshots(screensCheckBox.isSelected());
returnValue.setComposer(composerCheckBox.isSelected());
returnValue.setGame(gameCheckBox.isSelected());
return returnValue;
}
JButton getConnectButton()
{
if (connectButton == null)
{
connectButton = new JButton("Connect");
connectButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
Gb64comOptionsPanel.this.setCursor(waitCursor);
scraper.connectScraper(urlTextField.getText());
getConnectionStatusLabel().setText("Connection status: OK");
getConnectionStatusLabel().setIcon(new ImageIcon(this.getClass().getResource("/se/lantz/check.png")));
enableCheckBoxes(true);
okButton.setEnabled(true);
Gb64comOptionsPanel.this.setCursor(defaultCursor);
SwingUtilities.invokeLater(() -> SwingUtilities.getRootPane(connectButton).setDefaultButton(okButton));
}
catch (Exception e2)
{
getConnectionStatusLabel().setText("Connection status: Error. Invalid URL?");
getConnectionStatusLabel().setIcon(new ImageIcon(this.getClass().getResource("/se/lantz/failure.png")));
enableCheckBoxes(false);
okButton.setEnabled(false);
Gb64comOptionsPanel.this.setCursor(defaultCursor);
SwingUtilities.invokeLater(() -> SwingUtilities.getRootPane(connectButton).setDefaultButton(connectButton));
}
}
});
}
return connectButton;
}
private JLabel getConnectionStatusLabel()
{
if (connectionStatusLabel == null)
{
connectionStatusLabel = new JLabel(" ");
connectionStatusLabel.setFont(connectionStatusLabel.getFont().deriveFont(Font.BOLD));
connectionStatusLabel.setHorizontalTextPosition(SwingConstants.LEADING);
}
return connectionStatusLabel;
}
private JCheckBox getGenreCheckBox()
{
if (genreCheckBox == null)
{
genreCheckBox = new JCheckBox("Genre");
genreCheckBox.setSelected(true);
genreCheckBox.setEnabled(false);
}
return genreCheckBox;
}
private JCheckBox getComposerCheckBox()
{
if (composerCheckBox == null)
{
composerCheckBox = new JCheckBox("Composer");
composerCheckBox.setSelected(true);
composerCheckBox.setEnabled(false);
}
return composerCheckBox;
}
}

View File

@ -22,10 +22,13 @@ public class ScraperDialog extends BaseDialog
{
private static final String MOBY = "moby";
private static final String C64COM = "c64com";
private static final String GB64COM = "gb64com";
private static final String WWW_C64_COM = "www.c64.com";
private static final String WWW_MOBYGAMES_COM = "www.mobygames.com";
private static final String WWW_GAMEBASE_COM = "www.gb64.com";
private MobyGamesOptionsPanel mobyGamesPanel;
private C64comOptionsPanel c64comPanel;
private Gb64comOptionsPanel gb64comPanel;
private final ScraperManager scraper;
private CardLayout cardLayout = new CardLayout();
private JPanel scraperSelectionPanel;
@ -44,6 +47,7 @@ public class ScraperDialog extends BaseDialog
cardPanel.setLayout(cardLayout);
cardPanel.add(getMobyGamesPanel(), MOBY);
cardPanel.add(getC64comPanel(), C64COM);
cardPanel.add(getGb64comPanel(), GB64COM);
content.add(cardPanel, BorderLayout.CENTER);
addContent(content);
content.add(getScraperSelectionPanel(), BorderLayout.NORTH);
@ -67,6 +71,15 @@ public class ScraperDialog extends BaseDialog
}
return c64comPanel;
}
private Gb64comOptionsPanel getGb64comPanel()
{
if (gb64comPanel == null)
{
gb64comPanel = new Gb64comOptionsPanel(scraper, getOkButton());
}
return gb64comPanel;
}
public ScraperFields getScraperFields()
{
@ -136,16 +149,23 @@ public class ScraperDialog extends BaseDialog
scraper.setScrapertoUse(SCRAPER.moby);
getRootPane().setDefaultButton(getMobyGamesPanel().getConnectButton());
}
else
else if (scraperComboBox.getSelectedItem().equals(WWW_C64_COM))
{
cardLayout.show(cardPanel, C64COM);
scraper.setScrapertoUse(SCRAPER.c64com);
getRootPane().setDefaultButton(getC64comPanel().getConnectButton());
}
else
{
cardLayout.show(cardPanel, GB64COM);
scraper.setScrapertoUse(SCRAPER.gamebase);
getRootPane().setDefaultButton(getGb64comPanel().getConnectButton());
}
}
});
scraperComboBox.addItem(WWW_MOBYGAMES_COM);
scraperComboBox.addItem(WWW_C64_COM);
scraperComboBox.addItem(WWW_GAMEBASE_COM);
}
return scraperComboBox;
}

View File

@ -9,16 +9,18 @@ import se.lantz.model.MainViewModel;
import se.lantz.model.SystemModel;
import se.lantz.model.data.ScraperFields;
import se.lantz.scraper.C64comScraper;
import se.lantz.scraper.GamebaseScraper;
import se.lantz.scraper.MobyGamesScraper;
import se.lantz.scraper.Scraper;
public class ScraperManager
{
public enum SCRAPER {
moby, c64com
moby, c64com, gamebase
}
Scraper mobyScraper = new MobyGamesScraper();
Scraper c64comScraper = new C64comScraper();
Scraper gamebaseScraper = new GamebaseScraper();
Scraper usedScraper = mobyScraper;
List<BufferedImage> screenshotsList = new ArrayList<>();
@ -42,6 +44,9 @@ public class ScraperManager
case c64com:
usedScraper = c64comScraper;
break;
case gamebase:
usedScraper = gamebaseScraper;
break;
default:
break;
}

View File

@ -0,0 +1,137 @@
package se.lantz.scraper;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import se.lantz.model.data.ScraperFields;
public class GamebaseScraper implements Scraper
{
Map<String, String> genreMap = new HashMap<>();
private String gamebaseGameUrl;
private List<String> scrapedMusicList = new ArrayList<>();
private String scrapedTitle = "";
private String scrapedAuthor = "";
private int scrapedYear = 1985;
private String scrapedDescription = "";
private String scrapedGenre = "";
private String scrapedComposer = "";
private BufferedImage scrapedCover = null;
private File scrapedFile;
public GamebaseScraper()
{
//Keys are Genres defined on gamebase64.com, values are supported genres in the tool
//TODO
genreMap.put("Action / Adventure / Miscellaneous / Text adventure", "adventure");
genreMap.put("Racing / Driving", "driving");
genreMap.put("Strategy / Board game / Puzzle", "puzzle");
genreMap.put("Educational", "programming");
genreMap.put("Simulation / Simulator", "simulation");
genreMap.put("Sports", "sport");
genreMap.put("Maze / Breakout", "maze");
genreMap.put("Platform", "platform");
genreMap.put("Shoot'em up", "shoot");
}
@Override
public void connect(String url) throws IOException
{
this.gamebaseGameUrl = "";
Jsoup.connect(url).method(Connection.Method.GET).execute();
this.gamebaseGameUrl = url;
resetFields();
}
private void resetFields()
{
scrapedTitle = "";
scrapedYear = 1985;
scrapedAuthor = "";
scrapedComposer = "";
scrapedDescription = "";
scrapedCover = null;
scrapedGenre = "";
}
@Override
public void scrapeInformation(ScraperFields fields)
{
// TODO Auto-generated method stub
}
@Override
public String getTitle()
{
return scrapedTitle;
}
@Override
public String getAuthor()
{
return scrapedAuthor;
}
@Override
public int getYear()
{
return scrapedYear;
}
@Override
public String getDescription()
{
//Not supported, no description on c64.com
return "";
}
@Override
public String getGenre()
{
return scrapedGenre;
}
@Override
public String getComposer()
{
return String.join(", ", scrapedMusicList);
}
@Override
public BufferedImage getCover()
{
return scrapedCover;
}
@Override
public File getGameFile()
{
return scrapedFile;
}
@Override
public boolean isC64()
{
// Only C64 games available
return true;
}
@Override
public List<BufferedImage> scrapeScreenshots()
{
// TODO Auto-generated method stub
return new ArrayList<>();
}
}