Skip to content

Commit

Permalink
cf: allow for trailing slash on CF modpack page URL (#430)
Browse files Browse the repository at this point in the history
  • Loading branch information
itzg committed May 25, 2024
1 parent 01b3c38 commit e0a0902
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import me.itzg.helpers.McImageHelper;
import me.itzg.helpers.curseforge.ModpacksPageUrlParser.Parsed;
import me.itzg.helpers.files.ResultsFileWriter;
import me.itzg.helpers.files.TabularOutput;
import me.itzg.helpers.http.PathOrUri;
Expand Down Expand Up @@ -161,27 +160,15 @@ static class Listed {
@Option(names = "--missing-mods-filename", defaultValue = "MODS_NEED_DOWNLOAD.txt")
String missingModsFilename;

private static final Pattern PAGE_URL_PATTERN = Pattern.compile(
"https://(www|beta)\\.curseforge\\.com/minecraft/modpacks/(?<slug>.+?)(/(files|download)(/(?<fileId>\\d+)?)?)?");

@Override
public Integer call() throws Exception {
// https://www.curseforge.com/minecraft/modpacks/all-the-mods-8/files
// https://www.curseforge.com/minecraft/modpacks/all-the-mods-8/files/4248390

if (pageUrl != null) {
final Matcher m = PAGE_URL_PATTERN.matcher(pageUrl);
if (m.matches()) {
slug = m.group("slug");
final String fileIdStr = m.group("fileId");
if (fileIdStr != null) {
fileId = Integer.parseInt(fileIdStr);
}
}
else {
System.err.println("Unexpected URL structure: "+pageUrl);
return ExitCode.USAGE;
}
final Parsed parsed = ModpacksPageUrlParser.parse(pageUrl);
slug = parsed.getSlug();
fileId = parsed.getFileId();
}

if (slug == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package me.itzg.helpers.curseforge;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.Builder;
import lombok.Data;
import me.itzg.helpers.errors.InvalidParameterException;
import org.jetbrains.annotations.NotNull;

class ModpacksPageUrlParser {
private static final Pattern PAGE_URL_PATTERN = Pattern.compile(
"https://(www|beta)\\.curseforge\\.com/minecraft/modpacks/(?<slug>[^/]+?)(/((files|download)(/(?<fileId>\\d+)?)?)?)?");

@Data @Builder
public static class Parsed {
String slug;
Integer fileId;
}

@NotNull
public static Parsed parse(String pageUrl) {
if (pageUrl == null) {
return Parsed.builder().build();
}

final Matcher m = PAGE_URL_PATTERN.matcher(pageUrl);
if (m.matches()) {
final String slug = m.group("slug");
final String fileIdStr = m.group("fileId");
if (fileIdStr != null) {
return Parsed.builder()
.slug(slug)
.fileId(Integer.parseInt(fileIdStr))
.build();
}
else {
return Parsed.builder()
.slug(slug)
.build();
}
}
else {
throw new InvalidParameterException("Unexpected CF page URL structure: " + pageUrl);
}


}
}
3 changes: 3 additions & 0 deletions src/main/java/me/itzg/helpers/paper/PaperDownloadsClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import me.itzg.helpers.paper.model.VersionInfo;
import reactor.core.publisher.Mono;

/**
* <a href="https://api.papermc.io/docs/swagger-ui/index.html?configUrl=/openapi/swagger-config">Downloads API</a>
*/
public class PaperDownloadsClient implements AutoCloseable{

private final UriBuilder uriBuilder;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package me.itzg.helpers.curseforge;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import me.itzg.helpers.curseforge.ModpacksPageUrlParser.Parsed;
import me.itzg.helpers.errors.InvalidParameterException;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class ModpacksPageUrlParserTest {

@ParameterizedTest
@ValueSource(strings = {
"https://www.curseforge.com/minecraft/modpacks/create-perfect-world",
"https://beta.curseforge.com/minecraft/modpacks/create-perfect-world",
"https://www.curseforge.com/minecraft/modpacks/create-perfect-world/",
"https://www.curseforge.com/minecraft/modpacks/create-perfect-world/files",
"https://www.curseforge.com/minecraft/modpacks/create-perfect-world/files/",
})
void justSlug(String url) {
final Parsed parsed = ModpacksPageUrlParser.parse(url);
assertThat(parsed).isNotNull();
assertThat(parsed.getSlug()).isEqualTo("create-perfect-world");
assertThat(parsed.getFileId()).isNull();
}

@ParameterizedTest
@ValueSource(strings = {
"https://www.curseforge.com/minecraft/modpacks/create-perfect-world/files/5181367"
})
void slugAndFileId(String url) {
final Parsed parsed = ModpacksPageUrlParser.parse(url);
assertThat(parsed).isNotNull();
assertThat(parsed.getSlug()).isEqualTo("create-perfect-world");
assertThat(parsed.getFileId()).isEqualTo(5181367);
}

@ParameterizedTest
@ValueSource(strings = {
"",
"https://www.google.com",
"https://www.curseforge.com/minecraft/modpacks/create-perfect-world/wrong/",
"https://www.curseforge.com/minecraft/modpacks/create-perfect-world/invalid/5181367"
})
void invalid(String url) {
assertThatThrownBy(() -> ModpacksPageUrlParser.parse(url))
.isInstanceOf(InvalidParameterException.class);
}
}

0 comments on commit e0a0902

Please sign in to comment.