Skip to content

Commit ec59678

Browse files
committed
Released: '1.0.10'.
2 parents 8a8605d + 30455ba commit ec59678

10 files changed

Lines changed: 112 additions & 85 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version=1.0.9
1+
version=1.0.10

gradle/libs.versions.toml

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
1-
[versions]
2-
apache-commons-lang3 = "3.17.0"
3-
apache-http5 = "5.5"
4-
commons-io = "2.19.0"
5-
jakarta-inject = "2.0.1"
6-
jsoup = "1.20.1"
7-
lombok = "1.18.38"
8-
redisson = "3.49.0"
9-
researchgate = "3.1.0"
10-
spring-boot = "3.5.0"
11-
spring-dependencies = "1.1.7"
12-
struct = "2.2.0"
13-
version-catalog = "1.0.0"
14-
versions = "0.52.0"
15-
16-
[plugins]
17-
researchgate-release = { id = "net.researchgate.release", version.ref = "researchgate" }
18-
spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot" }
19-
spring-dependencies = { id = "io.spring.dependency-management", version.ref = "spring-dependencies" }
20-
version-catalog-update = { id = "nl.littlerobots.version-catalog-update", version.ref = "version-catalog" }
21-
versions = { id = "com.github.ben-manes.versions", version.ref = "versions" }
22-
23-
[libraries]
24-
apache-http5 = { module = "org.apache.httpcomponents.client5:httpclient5", version.ref = "apache-http5" }
25-
apache-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "apache-commons-lang3" }
26-
commons-io = { module = "commons-io:commons-io", version.ref = "commons-io" }
27-
jakarta-inject = { module = "jakarta.inject:jakarta.inject-api", version.ref = "jakarta-inject" }
28-
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
29-
lombok = { module = "org.projectlombok:lombok", version.ref = "lombok" }
30-
redisson = { module = "org.redisson:redisson-spring-data-35", version.ref = "redisson" }
31-
struct = { module = "org.thshsh:struct", version.ref = "struct" }
1+
[versions]
2+
apache-commons-lang3 = "3.18.0"
3+
apache-http5 = "5.5"
4+
commons-io = "2.20.0"
5+
jakarta-inject = "2.0.1"
6+
jsoup = "1.21.1"
7+
lombok = "1.18.38"
8+
redisson = "3.51.0"
9+
researchgate = "3.1.0"
10+
spring-boot = "3.5.5"
11+
spring-dependencies = "1.1.7"
12+
struct = "2.2.0"
13+
version-catalog = "1.0.0"
14+
versions = "0.52.0"
15+
16+
[plugins]
17+
researchgate-release = { id = "net.researchgate.release", version.ref = "researchgate" }
18+
spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot" }
19+
spring-dependencies = { id = "io.spring.dependency-management", version.ref = "spring-dependencies" }
20+
version-catalog-update = { id = "nl.littlerobots.version-catalog-update", version.ref = "version-catalog" }
21+
versions = { id = "com.github.ben-manes.versions", version.ref = "versions" }
22+
23+
[libraries]
24+
apache-http5 = { module = "org.apache.httpcomponents.client5:httpclient5", version.ref = "apache-http5" }
25+
apache-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "apache-commons-lang3" }
26+
commons-io = { module = "commons-io:commons-io", version.ref = "commons-io" }
27+
jakarta-inject = { module = "jakarta.inject:jakarta.inject-api", version.ref = "jakarta-inject" }
28+
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
29+
lombok = { module = "org.projectlombok:lombok", version.ref = "lombok" }
30+
redisson = { module = "org.redisson:redisson-spring-data-35", version.ref = "redisson" }
31+
struct = { module = "org.thshsh:struct", version.ref = "struct" }

src/main/java/io/arsha/api/controllers/AbstractController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,12 @@ protected List<CacheCompositeKey> categoryRequest(Category category, @NonNull St
125125
var mainCategory = category.getMainCategory();
126126
var subCategory = category.getSubCategory();
127127

128-
if (!categoryService.isValidCombination(mainCategory, subCategory)) {
128+
if (!categoryService.isValidCombination(mainCategory, subCategory, gameRegion)) {
129129
throw new MarketRequestException(category);
130130
}
131131

132132
if (subCategory == null) {
133-
var subCategories = categoryService.getSubCategories(mainCategory);
133+
var subCategories = categoryService.getSubCategories(mainCategory, gameRegion);
134134
return subCategories.stream().map(id -> createKey(null, mainCategory, id, gameRegion, MarketEndpoint.MARKET_LIST))
135135
.toList();
136136
} else {

src/main/java/io/arsha/api/data/market/MarketResponse.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ public boolean hasBadData() {
4949
return resultMessage == null || resultMessage.equals("0");
5050
}
5151

52+
@JsonIgnore
53+
public boolean cannotBeRegistered() {
54+
return resultCode == 8;
55+
}
56+
5257
@JsonIgnore
5358
public List<String> getResult() {
5459
return switch (resultMessage) {
@@ -60,4 +65,4 @@ public List<String> getResult() {
6065
};
6166
}
6267

63-
}
68+
}

src/main/java/io/arsha/api/data/market/common/GameRegion.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,8 @@ public static GameRegion fromValue(String region) {
4040

4141
return null;
4242
}
43+
44+
public boolean isConsole() {
45+
return this == CONSOLE_NA || this == CONSOLE_EU || this == CONSOLE_ASIA;
46+
}
4347
}

src/main/java/io/arsha/api/exceptions/CannotBeRegisteredException.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ public class CannotBeRegisteredException extends AbstractException {
88
@Getter
99
private final MarketResponse response;
1010

11-
public CannotBeRegisteredException(String response) {
11+
public CannotBeRegisteredException(MarketResponse response) {
1212
super();
13-
this.response = MarketResponse.deserialize(response);
13+
this.response = response;
1414
}
1515

1616
}
Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.arsha.api.lib;
22

3-
import io.arsha.api.exceptions.CannotBeRegisteredException;
43
import jakarta.annotation.Nullable;
54
import jakarta.validation.constraints.NotNull;
65
import java.io.ByteArrayInputStream;
@@ -14,19 +13,10 @@
1413
import org.thshsh.struct.Struct;
1514

1615
// Implementation from https://github.com/shrddr/huffman_heap
16+
// This isn't entirely accurate anymore, but it used to basically be a direct copy so im keeping it
1717
@Component
1818
public class HuffmanDecoder {
1919

20-
record Node(@Nullable String character, @NotNull Long frequency, @Nullable Node left, @Nullable Node right) {
21-
public static Node fromEntry(Map.Entry<String, Long> entry) {
22-
return new Node(entry.getKey(), entry.getValue(), null, null);
23-
}
24-
25-
public static Node branch(Node left, Node right) {
26-
return new Node(null, left.frequency() + right.frequency(), left, right);
27-
}
28-
}
29-
3020
private static Map<String, Long> getFrequencies(InputStream buffer) throws IOException {
3121
var data = Struct.create("<3I").unpack(buffer);
3222
var chars = (long) data.get(2);
@@ -35,7 +25,7 @@ private static Map<String, Long> getFrequencies(InputStream buffer) throws IOExc
3525
for (int i = 0; i < chars; i++) {
3626
var charData = Struct.create("<Ic3b").unpack(buffer);
3727
var frequency = (long) charData.get(0);
38-
var character = new String(new byte[] { (byte) charData.get(1) });
28+
var character = new String(new byte[]{(byte) charData.get(1)});
3929
frequencyMap.put(character, frequency);
4030
}
4131
return frequencyMap;
@@ -45,9 +35,7 @@ private static Node getRoot(InputStream stream) throws IOException {
4535
var frequencies = getFrequencies(stream);
4636

4737
var heap = new PriorityQueue<>(Comparator.comparingLong(Node::frequency));
48-
frequencies.entrySet().stream()
49-
.map(Node::fromEntry)
50-
.forEach(heap::add);
38+
frequencies.entrySet().stream().map(Node::fromEntry).forEach(heap::add);
5139

5240
while (heap.size() > 1) {
5341
var left = heap.poll();
@@ -62,40 +50,50 @@ private static Node getRoot(InputStream stream) throws IOException {
6250
return heap.peek();
6351
}
6452

65-
private static String unpack(Node root, StringBuilder packed) {
53+
public String unpack(byte[] buffer) throws IOException {
54+
var stream = new ByteArrayInputStream(buffer);
55+
56+
var root = getRoot(stream);
57+
var sizes = Struct.create("<3I").unpack(stream);
58+
var bits = (long) sizes.getFirst(); // The bit size of the encoded data
59+
// var bytes = (long) sizes.get(1); // The byte size of the encoded data
60+
var expectedBytes = (long) sizes.get(2); // The expected byte size of the unpacked data
61+
62+
var counter = 0;
6663
var current = root;
6764
var unpacked = new StringBuilder();
68-
for (var i = 0; i < packed.length(); i++) {
69-
current = packed.charAt(i) == '0' ? current.left() : current.right();
70-
assert current != null;
65+
outer:
66+
for (var b : stream.readAllBytes()) {
67+
if (unpacked.length() > expectedBytes) {
68+
throw new IllegalStateException("Unpacked data exceeds expected size");
69+
}
7170

72-
if (current.left() == null && current.right() == null) {
73-
unpacked.append(current.character());
74-
current = root;
71+
for (int i = 7; i >= 0; i--) {
72+
if (counter >= bits) {
73+
break outer;
74+
}
75+
int bit = (b >> i) & 1;
76+
current = bit == 0 ? current.left() : current.right();
77+
assert current != null;
78+
if (current.left() == null && current.right() == null) {
79+
unpacked.append(current.character());
80+
current = root;
81+
}
82+
counter++;
7583
}
7684
}
85+
7786
return unpacked.toString();
7887
}
7988

80-
public String decode(byte[] buffer) throws CannotBeRegisteredException, IOException {
81-
var testResult = new String(buffer);
82-
if (testResult.contains("resultMsg")) { // Probably an item that can't be registered on market (code 8)
83-
throw new CannotBeRegisteredException(testResult);
84-
}
85-
86-
var dataIn = new ByteArrayInputStream(buffer);
87-
var root = getRoot(dataIn);
88-
89-
var data = Struct.create("<3I").unpack(dataIn);
90-
var bits = (long) data.getFirst(); // The bit size of the encoded data
91-
// var bytes = (long) data.get(1); // The byte size of the encoded data
92-
// var expectedSize = (long) data.get(2); // The expected byte size of the unpacked data
89+
record Node(@Nullable String character, @NotNull Long frequency, @Nullable Node left, @Nullable Node right) {
9390

94-
var bin = new StringBuilder();
95-
for (byte b : dataIn.readAllBytes())
96-
bin.append(Integer.toBinaryString(b & 255 | 256).substring(1));
97-
if (bin.length() > bits) bin.setLength(Math.toIntExact(bits));
91+
public static Node fromEntry(Map.Entry<String, Long> entry) {
92+
return new Node(entry.getKey(), entry.getValue(), null, null);
93+
}
9894

99-
return unpack(root, bin);
95+
public static Node branch(Node left, Node right) {
96+
return new Node(null, left.frequency() + right.frequency(), left, right);
97+
}
10098
}
10199
}

src/main/java/io/arsha/api/services/MarketCategoryService.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io.arsha.api.config.MarketCategoriesConfiguration.MarketCategories;
44
import io.arsha.api.config.MarketCategoriesConfiguration.MarketCategory;
55
import io.arsha.api.config.MarketCategoriesConfiguration.MarketSubCategory;
6+
import io.arsha.api.data.market.common.GameRegion;
67
import jakarta.annotation.Nullable;
78
import java.util.List;
89
import java.util.Objects;
@@ -24,26 +25,30 @@ public List<Long> getMainCategories() {
2425
.toList();
2526
}
2627

27-
public List<Long> getSubCategories(Long mainCategory) {
28+
public List<Long> getSubCategories(Long mainCategory, GameRegion region) {
2829
var category = marketCategories.stream()
2930
.filter(c -> Objects.equals(c.id(), mainCategory))
3031
.findFirst()
3132
.orElseThrow();
3233

33-
return category.subCategories().stream()
34-
.map(MarketSubCategory::id)
35-
.toList();
34+
var subCategories = category.subCategories().stream().map(MarketSubCategory::id);
35+
if (region.isConsole() && category.id() == 30) {
36+
// Special case for console categories, subcategory 3 of category 30 is not available
37+
subCategories = subCategories.filter(sid -> sid != 3);
38+
}
39+
40+
return subCategories.toList();
3641
}
3742

3843
public boolean isValidCategory(Long category) {
3944
return marketCategories.stream()
4045
.anyMatch(c -> Objects.equals(c.id(), category));
4146
}
4247

43-
public boolean isValidCombination(Long mainCategory, @Nullable Long subCategory) {
48+
public boolean isValidCombination(Long mainCategory, @Nullable Long subCategory, GameRegion region) {
4449
if (!isValidCategory(mainCategory)) return false;
4550

46-
return subCategory == null || getSubCategories(mainCategory).stream()
51+
return subCategory == null || getSubCategories(mainCategory, region).stream()
4752
.anyMatch(s -> s.equals(subCategory));
4853
}
4954

src/main/java/io/arsha/api/services/MarketRequestService.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,15 @@ public CompletableFuture<Tuple2<CacheCompositeKey, Optional<MarketResponse>>> re
102102
public String huffmanDecode(byte[] data) throws CannotBeRegisteredException, IOException, MarketResponseBodyException {
103103
var testString = new String(data);
104104
if (testString.contains("resultMsg")) {
105-
throw new CannotBeRegisteredException(testString);
105+
var marketResponse = MarketResponse.deserialize(testString);
106+
if (marketResponse.cannotBeRegistered()) {
107+
throw new CannotBeRegisteredException(marketResponse);
108+
}
106109
}
107110

108111
// Starts with HTML opening tag, probably blocked by Imperva
109112
if (testString.startsWith("<html")) throw new MarketResponseBodyException();
110113

111-
return huffmanDecoder.decode(data);
114+
return huffmanDecoder.unpack(data);
112115
}
113116
}

src/main/resources/categories.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@
9494
{
9595
"id": "23",
9696
"name": "Revolvers"
97+
},
98+
{
99+
"id": "24",
100+
"name": "Power Pole"
97101
}
98102
]
99103
},
@@ -184,6 +188,10 @@
184188
{
185189
"id": "21",
186190
"name": "Shotgun"
191+
},
192+
{
193+
"id": "22",
194+
"name": "Gourd Bottle"
187195
}
188196
]
189197
},
@@ -302,6 +310,10 @@
302310
{
303311
"id": "29",
304312
"name": "Lil' Devil"
313+
},
314+
{
315+
"id": "30",
316+
"name": "Jade Pillar"
305317
}
306318
]
307319
},

0 commit comments

Comments
 (0)