Initial commit.

This commit is contained in:
cobi 2025-03-19 02:04:18 -04:00
commit 289ab08272
22 changed files with 946 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.idea
target
*.iml

74
pom.xml Normal file
View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>name.amethyst</groupId>
<artifactId>amethyst-wiki-bot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Amethyst Wiki Bot</name>
<url>https://amethyst.name</url>
<repositories>
<repository>
<id>central</id>
<name>Maven Central</name>
<url>https://repo1.maven.org/maven2/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.18.0</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.11</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>4.0.0-M1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>4.0.0-M1</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.10.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>4.0.0-beta-1</version>
<configuration>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,5 @@
package name.amethyst.wikibot.restapi;
public class MediaWikiRestApi {
}

View file

@ -0,0 +1,66 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import jakarta.ws.rs.core.MediaType;
import java.util.EnumSet;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public enum ContentModel {
CSS("css", new MediaType("text", "css")),
JAVASCRIPT("javascript", new MediaType("text", "javascript")),
JSON("json", MediaType.APPLICATION_JSON_TYPE),
TEXT("text", MediaType.TEXT_PLAIN_TYPE),
WIKITEXT("wikitext", new MediaType("text", "x-wiki")),
CAMPAIGN("Campaign", MediaType.APPLICATION_JSON_TYPE),
ENTITY_SCHEMA("EntitySchema", MediaType.APPLICATION_JSON_TYPE),
FLOW_BOARD("flow-board", MediaType.APPLICATION_JSON_TYPE),
GEO_JSON("GeoJson", MediaType.APPLICATION_JSON_TYPE),
JSON_BOOK("JsonBook", MediaType.APPLICATION_JSON_TYPE),
JSON_CONFIG("JsonConfig", new MediaType("application", "json+pretty")),
JSON_SCHEMA("JsonSchema", MediaType.APPLICATION_JSON_TYPE),
MASS_MESSAGE_LIST_CONTENT("MassMessageListContent", MediaType.WILDCARD_TYPE),
WIKIBASE_MEDIAINFO("wikibase-mediainfo", MediaType.APPLICATION_JSON_TYPE),
PROOFREAD_INDEX("proofread-index", new MediaType("text", "x-wiki")),
PROOFREAD_PAGE("proofread-page", new MediaType("text", "x-wiki")),
SANITIZED_CSS("sanitized-css", new MediaType("text", "css")),
SCRIBUNTU("Scribuntu", MediaType.TEXT_PLAIN_TYPE),
SECURE_POLL("SecurePoll", MediaType.APPLICATION_JSON_TYPE),
SEMANTIC_MEDIA_WIKI("smw/schema", MediaType.APPLICATION_JSON_TYPE),
SYNTAX_HIGHLIGHT("syntaxhighlight", MediaType.WILDCARD_TYPE),
TEI("tei", new MediaType("application", "tei+xml")),
WIKIBASE_ITEM("wikibase-item", MediaType.APPLICATION_JSON_TYPE),
WIKIBASE_LEXEME("wikibase-lexeme", MediaType.APPLICATION_JSON_TYPE),
WIKIBASE_PROPERTY("wikibase-property", MediaType.APPLICATION_JSON_TYPE),
;
private static final Map<String, ContentModel> BY_STRING_VALUE = EnumSet
.allOf(ContentModel.class)
.stream()
.collect(Collectors.toMap(ContentModel::toString, Function.identity()));
@JsonCreator
public static ContentModel fromString(final String value) {
return BY_STRING_VALUE.get(value);
}
private final String stringValue;
private final MediaType mediaType;
ContentModel(final String stringValue, final MediaType mediaType) {
this.stringValue = stringValue;
this.mediaType = mediaType;
}
@JsonValue
public String getStringValue() {
return stringValue;
}
public MediaType getMediaType() {
return mediaType;
}
}

View file

@ -0,0 +1,63 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Optional;
@JsonIgnoreProperties(ignoreUnknown = true)
public class CreatePageRequest {
@JsonProperty
private String source;
@JsonProperty
private String title;
@JsonProperty
private String comment;
@JsonProperty("content_model")
private Optional<ContentModel> contentModel;
@JsonProperty
private Optional<String> token;
public CreatePageRequest() {
}
public String getSource() {
return source;
}
public void setSource(final String source) {
this.source = source;
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
public String getComment() {
return comment;
}
public void setComment(final String comment) {
this.comment = comment;
}
public Optional<ContentModel> getContentModel() {
return contentModel;
}
public void setContentModel(final Optional<ContentModel> contentModel) {
this.contentModel = contentModel;
}
public Optional<String> getToken() {
return token;
}
public void setToken(final Optional<String> token) {
this.token = token;
}
}

View file

@ -0,0 +1,17 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.net.URI;
@JsonIgnoreProperties(ignoreUnknown = true)
public class File {
@JsonProperty
private String title;
@JsonProperty("file_description_url")
private URI fileDescriptionUrl;
private FileRevisionRef latest;
private FileThumbnail preferred;
private FileThumbnail original;
}

View file

@ -0,0 +1,38 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import java.util.EnumSet;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public enum FileMediaType {
BITMAP, DRAWING, AUDIO, VIDEO, MULTIMEDIA, UNKNOWN, OFFICE, TEXT, EXECUTABLE, ARCHIVE, THREE_D("3D");
private static final Map<String, FileMediaType> BY_STRING_VALUE = EnumSet
.allOf(FileMediaType.class)
.stream()
.collect(Collectors.toMap(FileMediaType::toString, Function.identity()));
@JsonCreator
public static FileMediaType fromString(final String value) {
return BY_STRING_VALUE.get(value);
}
private final String stringValue;
FileMediaType() {
this.stringValue = name();
}
FileMediaType(final String stringValue) {
this.stringValue = stringValue;
}
@JsonValue
public String getStringValue() {
return stringValue;
}
}

View file

@ -0,0 +1,45 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import java.time.Instant;
@JsonIgnoreProperties(ignoreUnknown = true)
public class FileRevisionRef {
@JsonProperty
private Instant timestamp;
@JsonProperty
private UserRef user;
public FileRevisionRef() {
}
public Instant getTimestamp() {
return timestamp;
}
public void setTimestamp(final Instant timestamp) {
this.timestamp = timestamp;
}
@JsonGetter("timestamp")
public String getTimestampJson() {
return timestamp.toString();
}
@JsonSetter("timestamp")
public void setTimestampJson(final String stringValue) {
this.timestamp = Instant.parse(stringValue);
}
public UserRef getUser() {
return user;
}
public void setUser(final UserRef user) {
this.user = user;
}
}

View file

@ -0,0 +1,74 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.net.URI;
import java.util.Optional;
@JsonIgnoreProperties(ignoreUnknown = true)
public class FileThumbnail {
@JsonProperty("mediatype")
private FileMediaType mediaType;
@JsonProperty
private Optional<Long> size;
@JsonProperty
private Optional<Long> width;
@JsonProperty
private Optional<Long> height;
@JsonProperty
private Optional<Long> duration;
@JsonProperty
private URI url;
public FileThumbnail() {
}
public FileMediaType getMediaType() {
return mediaType;
}
public void setMediaType(final FileMediaType mediaType) {
this.mediaType = mediaType;
}
public Optional<Long> getSize() {
return size;
}
public void setSize(final Optional<Long> size) {
this.size = size;
}
public Optional<Long> getWidth() {
return width;
}
public void setWidth(final Optional<Long> width) {
this.width = width;
}
public Optional<Long> getHeight() {
return height;
}
public void setHeight(final Optional<Long> height) {
this.height = height;
}
public Optional<Long> getDuration() {
return duration;
}
public void setDuration(final Optional<Long> duration) {
this.duration = duration;
}
public URI getUrl() {
return url;
}
public void setUrl(final URI url) {
this.url = url;
}
}

View file

@ -0,0 +1,21 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class GetFile extends File {
@JsonProperty
private FileThumbnail thumbnail;
public GetFile() {
}
public FileThumbnail getThumbnail() {
return thumbnail;
}
public void setThumbnail(final FileThumbnail thumbnail) {
this.thumbnail = thumbnail;
}
}

View file

@ -0,0 +1,23 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.net.URL;
@JsonIgnoreProperties(ignoreUnknown = true)
public class GetPage extends Page {
@JsonProperty("html_url")
private URL htmlUrl;
public GetPage() {
}
public URL getHtmlUrl() {
return htmlUrl;
}
public void setHtmlUrl(final URL htmlUrl) {
this.htmlUrl = htmlUrl;
}
}

View file

@ -0,0 +1,21 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class GetPageOffline extends Page {
@JsonProperty
private String html;
public GetPageOffline() {
}
public String getHtml() {
return html;
}
public void setHtml(final String html) {
this.html = html;
}
}

View file

@ -0,0 +1,33 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.net.URI;
@JsonIgnoreProperties(ignoreUnknown = true)
public class License {
@JsonProperty
private URI url;
@JsonProperty
private String title;
public License() {
}
public URI getUrl() {
return url;
}
public void setUrl(final URI url) {
this.url = url;
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
}

View file

@ -0,0 +1,71 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Page {
@JsonProperty
private long id;
@JsonProperty
private String key;
@JsonProperty
private String title;
@JsonProperty
private RevisionRef latest;
@JsonProperty
private ContentModel contentModel;
@JsonProperty
private License license;
public Page() {
}
public long getId() {
return id;
}
public void setId(final long id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(final String key) {
this.key = key;
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
public RevisionRef getLatest() {
return latest;
}
public void setLatest(final RevisionRef latest) {
this.latest = latest;
}
public ContentModel getContentModel() {
return contentModel;
}
public void setContentModel(final ContentModel contentModel) {
this.contentModel = contentModel;
}
public License getLicense() {
return license;
}
public void setLicense(final License license) {
this.license = license;
}
}

View file

@ -0,0 +1,51 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class PageLanguage {
@JsonProperty
private String code;
@JsonProperty
private String name;
@JsonProperty
private String key;
@JsonProperty
private String title;
public PageLanguage() {
}
public String getCode() {
return code;
}
public void setCode(final String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getKey() {
return key;
}
public void setKey(final String key) {
this.key = key;
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
}

View file

@ -0,0 +1,21 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class PageWithSource extends Page {
@JsonProperty
private String source;
public PageWithSource() {
}
public String getSource() {
return source;
}
public void setSource(final String source) {
this.source = source;
}
}

View file

@ -0,0 +1,45 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import java.time.Instant;
@JsonIgnoreProperties(ignoreUnknown = true)
public class RevisionRef {
@JsonProperty
private long id;
@JsonProperty
private Instant timestamp;
public RevisionRef() {
}
public long getId() {
return id;
}
public void setId(final long id) {
this.id = id;
}
public Instant getTimestamp() {
return timestamp;
}
public void setTimestamp(final Instant timestamp) {
this.timestamp = timestamp;
}
@JsonGetter("timestamp")
public String getTimestampJson() {
return timestamp.toString();
}
@JsonSetter("timestamp")
public void setTimestampJson(final String stringValue) {
this.timestamp = Instant.parse(stringValue);
}
}

View file

@ -0,0 +1,23 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
public class SearchResponse {
@JsonProperty
private List<SearchResult> pages;
public SearchResponse() {
}
public List<SearchResult> getPages() {
return pages;
}
public void setPages(final List<SearchResult> pages) {
this.pages = pages;
}
}

View file

@ -0,0 +1,83 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Optional;
@JsonIgnoreProperties(ignoreUnknown = true)
public class SearchResult {
@JsonProperty
private long id;
@JsonProperty
private String key;
@JsonProperty
private String title;
@JsonProperty
private String excerpt;
@JsonProperty("matched_title")
private Optional<String> matchedTitle;
@JsonProperty
private String description;
@JsonProperty
private Optional<SearchThumbnail> thumbnail;
public SearchResult() {
}
public long getId() {
return id;
}
public void setId(final long id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(final String key) {
this.key = key;
}
public String getTitle() {
return title;
}
public void setTitle(final String title) {
this.title = title;
}
public String getExcerpt() {
return excerpt;
}
public void setExcerpt(final String excerpt) {
this.excerpt = excerpt;
}
public Optional<String> getMatchedTitle() {
return matchedTitle;
}
public void setMatchedTitle(final Optional<String> matchedTitle) {
this.matchedTitle = matchedTitle;
}
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
public Optional<SearchThumbnail> getThumbnail() {
return thumbnail;
}
public void setThumbnail(final Optional<SearchThumbnail> thumbnail) {
this.thumbnail = thumbnail;
}
}

View file

@ -0,0 +1,75 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.ws.rs.core.MediaType;
import java.net.URI;
import java.util.Optional;
@JsonIgnoreProperties(ignoreUnknown = true)
public class SearchThumbnail {
@JsonProperty("mimetype")
private MediaType mimeType;
@JsonProperty
private Optional<Long> size;
@JsonProperty
private Optional<Long> width;
@JsonProperty
private Optional<Long> height;
@JsonProperty
private Optional<Long> duration;
@JsonProperty
private URI url;
public SearchThumbnail() {
}
public MediaType getMimeType() {
return mimeType;
}
public void setMimeType(final MediaType mimeType) {
this.mimeType = mimeType;
}
public Optional<Long> getSize() {
return size;
}
public void setSize(final Optional<Long> size) {
this.size = size;
}
public Optional<Long> getWidth() {
return width;
}
public void setWidth(final Optional<Long> width) {
this.width = width;
}
public Optional<Long> getHeight() {
return height;
}
public void setHeight(final Optional<Long> height) {
this.height = height;
}
public Optional<Long> getDuration() {
return duration;
}
public void setDuration(final Optional<Long> duration) {
this.duration = duration;
}
public URI getUrl() {
return url;
}
public void setUrl(final URI url) {
this.url = url;
}
}

View file

@ -0,0 +1,63 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Optional;
@JsonIgnoreProperties(ignoreUnknown = true)
public class UpdatePageRequest {
@JsonProperty
private String source;
@JsonProperty
private String comment;
@JsonProperty
private Optional<RevisionRef> latest;
@JsonProperty("content_model")
private Optional<ContentModel> contentModel;
@JsonProperty
private Optional<String> token;
public UpdatePageRequest() {
}
public String getSource() {
return source;
}
public void setSource(final String source) {
this.source = source;
}
public String getComment() {
return comment;
}
public void setComment(final String comment) {
this.comment = comment;
}
public Optional<RevisionRef> getLatest() {
return latest;
}
public void setLatest(final Optional<RevisionRef> latest) {
this.latest = latest;
}
public Optional<ContentModel> getContentModel() {
return contentModel;
}
public void setContentModel(final Optional<ContentModel> contentModel) {
this.contentModel = contentModel;
}
public Optional<String> getToken() {
return token;
}
public void setToken(final Optional<String> token) {
this.token = token;
}
}

View file

@ -0,0 +1,31 @@
package name.amethyst.wikibot.restapi.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserRef {
@JsonProperty
private long id;
@JsonProperty
private String name;
public UserRef() {
}
public long getId() {
return id;
}
public void setId(final long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}