Skip to content

Commit f099ccd

Browse files
committed
Add /cwiki command
1 parent 1c33afd commit f099ccd

File tree

5 files changed

+220
-1
lines changed

5 files changed

+220
-1
lines changed

src/main/java/net/earthcomputer/clientcommands/ClientCommands.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ public static void registerCommands(CommandDispatcher<ServerCommandSource> dispa
2626
TempRuleCommand.register(dispatcher);
2727
RenderCommand.register(dispatcher);
2828
CHelpCommand.register(dispatcher);
29+
WikiCommand.register(dispatcher);
2930
}
3031
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package net.earthcomputer.clientcommands;
2+
3+
import com.google.gson.Gson;
4+
import net.minecraft.ChatFormat;
5+
6+
import java.io.IOException;
7+
import java.io.InputStream;
8+
import java.io.InputStreamReader;
9+
import java.io.UnsupportedEncodingException;
10+
import java.net.*;
11+
import java.util.Locale;
12+
import java.util.Map;
13+
import java.util.regex.Matcher;
14+
import java.util.regex.Pattern;
15+
16+
public class WikiRetriever {
17+
18+
private static final String WIKI_HOST = "https://minecraft.gamepedia.com/";
19+
private static final String PAGE_SUMMARY_QUERY = WIKI_HOST + "api.php?action=query&prop=extracts&exintro=true&format=json&titles=%s";
20+
private static final Pattern HTML_TAG_PATTERN = Pattern.compile("<\\s*(/)?\\s*(\\w+).*?>", Pattern.DOTALL);
21+
private static final ChatFormat CODE_COLOR = ChatFormat.DARK_GREEN;
22+
private static final Gson GSON = new Gson();
23+
24+
public static String decode(String html) {
25+
Matcher matcher = HTML_TAG_PATTERN.matcher(html);
26+
StringBuffer raw = new StringBuffer();
27+
28+
boolean bold = false, italic = false, underline = false, code = false;
29+
30+
// -1 for not in list, 0 for unordered list, >= 1 for ordered list
31+
int listIndex = -1;
32+
33+
while (matcher.find()) {
34+
matcher.appendReplacement(raw, "");
35+
36+
boolean endTag = matcher.group(1) != null;
37+
String tagName = matcher.group(2).toLowerCase(Locale.ENGLISH);
38+
39+
if (!endTag) {
40+
switch (tagName) {
41+
case "b":
42+
raw.append(ChatFormat.BOLD);
43+
bold = true;
44+
break;
45+
case "i":
46+
raw.append(ChatFormat.ITALIC);
47+
italic = true;
48+
break;
49+
case "u":
50+
case "dt":
51+
raw.append(ChatFormat.UNDERLINE);
52+
underline = true;
53+
break;
54+
case "code":
55+
raw.append(CODE_COLOR);
56+
if (bold) raw.append(ChatFormat.BOLD);
57+
if (italic) raw.append(ChatFormat.ITALIC);
58+
if (underline) raw.append(ChatFormat.UNDERLINE);
59+
code = true;
60+
break;
61+
case "dd":
62+
raw.append(" ");
63+
break;
64+
case "ul":
65+
listIndex = 0;
66+
break;
67+
case "ol":
68+
listIndex = 1;
69+
break;
70+
case "li":
71+
if (listIndex >= 1) {
72+
raw.append(" ").append(listIndex).append(". ");
73+
listIndex++;
74+
} else {
75+
raw.append(" \u2022");
76+
}
77+
break;
78+
case "br":
79+
raw.append("\n");
80+
}
81+
} else {
82+
switch (tagName) {
83+
case "b":
84+
if (code) raw.append(CODE_COLOR);
85+
else raw.append(ChatFormat.RESET);
86+
if (italic) raw.append(ChatFormat.ITALIC);
87+
if (underline) raw.append(ChatFormat.UNDERLINE);
88+
bold = false;
89+
break;
90+
case "i":
91+
if (code) raw.append(CODE_COLOR);
92+
else raw.append(ChatFormat.RESET);
93+
if (bold) raw.append(ChatFormat.BOLD);
94+
if (underline) raw.append(ChatFormat.UNDERLINE);
95+
italic = false;
96+
break;
97+
case "dt":
98+
raw.append("\n");
99+
//fallthrough
100+
case "u":
101+
if (code) raw.append(CODE_COLOR);
102+
else raw.append(ChatFormat.RESET);
103+
if (bold) raw.append(ChatFormat.BOLD);
104+
if (italic) raw.append(ChatFormat.ITALIC);
105+
underline = false;
106+
break;
107+
case "code":
108+
raw.append(ChatFormat.RESET);
109+
if (bold) raw.append(ChatFormat.BOLD);
110+
if (italic) raw.append(ChatFormat.ITALIC);
111+
if (underline) raw.append(ChatFormat.UNDERLINE);
112+
code = false;
113+
break;
114+
case "ul":
115+
case "ol":
116+
listIndex = -1;
117+
break;
118+
case "dd":
119+
case "li":
120+
case "br":
121+
case "p":
122+
raw.append("\n");
123+
break;
124+
}
125+
}
126+
}
127+
matcher.appendTail(raw);
128+
129+
String rawStr = raw.toString();
130+
rawStr = rawStr.replace("&quot;", "\"");
131+
rawStr = rawStr.replace("&#39;", "'");
132+
rawStr = rawStr.replace("&lt;", "<");
133+
rawStr = rawStr.replace("&gt;", ">");
134+
rawStr = rawStr.replace("&amp;", "&");
135+
136+
return rawStr;
137+
}
138+
139+
public static String getWikiSummary(String pageName) {
140+
URL url;
141+
try {
142+
String encodedPage = URLEncoder.encode(pageName, "UTF-8");
143+
url = new URL(String.format(PAGE_SUMMARY_QUERY, encodedPage));
144+
} catch (UnsupportedEncodingException | MalformedURLException e) {
145+
return null;
146+
}
147+
148+
QueryResult result;
149+
try (InputStream in = url.openConnection().getInputStream()) {
150+
result = GSON.fromJson(new InputStreamReader(in), QueryResult.class);
151+
} catch (IOException e) {
152+
return null;
153+
}
154+
155+
if (result.query.pages.isEmpty())
156+
return null;
157+
QueryResult.Query.Page page = result.query.pages.values().iterator().next();
158+
if (page.missing != null || page.extract == null)
159+
return null;
160+
String html = page.extract;
161+
return decode(html);
162+
}
163+
164+
private static class QueryResult {
165+
public String batchcomplete;
166+
public Query query;
167+
private static class Query {
168+
private Map<String, Page> pages;
169+
private static class Page {
170+
public int pageid;
171+
public String title;
172+
public String extract;
173+
public String missing;
174+
}
175+
}
176+
}
177+
178+
}

src/main/java/net/earthcomputer/clientcommands/command/CHelpCommand.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import net.minecraft.network.chat.TranslatableComponent;
1010
import net.minecraft.server.command.ServerCommandSource;
1111

12-
import java.util.LinkedHashMap;
1312
import java.util.Map;
1413

1514
import static com.mojang.brigadier.arguments.StringArgumentType.*;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package net.earthcomputer.clientcommands.command;
2+
3+
import com.mojang.brigadier.CommandDispatcher;
4+
import net.earthcomputer.clientcommands.WikiRetriever;
5+
import net.minecraft.network.chat.TextComponent;
6+
import net.minecraft.network.chat.TranslatableComponent;
7+
import net.minecraft.server.command.ServerCommandSource;
8+
9+
import static com.mojang.brigadier.arguments.StringArgumentType.*;
10+
import static net.earthcomputer.clientcommands.command.ClientCommandManager.*;
11+
import static net.minecraft.server.command.CommandManager.*;
12+
13+
public class WikiCommand {
14+
15+
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
16+
addClientSideCommand("cwiki");
17+
18+
dispatcher.register(literal("cwiki")
19+
.then(argument("page", greedyString())
20+
.executes(ctx -> displayWikiPage(ctx.getSource(), getString(ctx, "page")))));
21+
}
22+
23+
private static int displayWikiPage(ServerCommandSource source, String page) {
24+
String content = WikiRetriever.getWikiSummary(page);
25+
26+
if (content == null) {
27+
sendError(new TranslatableComponent("commands.cwiki.failed"));
28+
return 0;
29+
}
30+
31+
content = content.trim();
32+
for (String line : content.split("\n")) {
33+
sendFeedback(new TextComponent(line));
34+
}
35+
36+
return content.length();
37+
}
38+
39+
}

src/main/resources/assets/clientcommands/lang/en_us.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,7 @@
3131
"commands.ctemprule.reset.success": "TempRule %s has been reset to %s",
3232
"commands.ctemprule.set.success": "TempRule %s has been updated to %s",
3333

34+
"commands.cwiki.failed": "Could not retrieve wiki content",
35+
3436
"commands.client.blockpos": "(%d, %d, %d)"
3537
}

0 commit comments

Comments
 (0)