From 1bec86dd17982e398967e3589db7f50460857e20 Mon Sep 17 00:00:00 2001 From: Mouamle Date: Sun, 22 Sep 2019 18:56:14 +0300 Subject: [PATCH] Release --- src/main/java/mouamle/tggh/Application.java | 12 + .../mouamle/tggh/common/ServiceInterface.java | 5 + .../java/mouamle/tggh/common/Settings.java | 33 + src/main/java/mouamle/tggh/common/Tokens.java | 27 + .../mouamle/tggh/github/GithubInterface.java | 12 + .../tggh/github/service/GithubService.java | 30 + .../tggh/github/web/IssuesEndpoint.java | 52 ++ .../tggh/github/web/model/Assignee.java | 217 +++++ .../tggh/github/web/model/Changes.java | 16 + .../tggh/github/web/model/Creator.java | 217 +++++ .../mouamle/tggh/github/web/model/Issue.java | 302 +++++++ .../tggh/github/web/model/IssueEvent.java | 74 ++ .../mouamle/tggh/github/web/model/Label.java | 85 ++ .../tggh/github/web/model/License.java | 74 ++ .../tggh/github/web/model/Milestone.java | 195 +++++ .../mouamle/tggh/github/web/model/Owner.java | 217 +++++ .../tggh/github/web/model/Repository.java | 818 ++++++++++++++++++ .../mouamle/tggh/github/web/model/Sender.java | 213 +++++ .../mouamle/tggh/github/web/model/User.java | 213 +++++ .../tggh/github/web/service/IssuesBus.java | 8 + .../github/web/service/PayloadRegistry.java | 34 + .../tggh/telegram/TelegramInterface.java | 41 + .../tggh/telegram/bot/IssueTrackerBot.java | 228 +++++ .../bot/service/IssueHookHandler.java | 26 + .../tggh/util/bus/AbstractEventBus.java | 26 + .../java/mouamle/tggh/util/bus/EventBus.java | 23 + src/main/resources/application.properties | 11 + 27 files changed, 3209 insertions(+) create mode 100644 src/main/java/mouamle/tggh/common/ServiceInterface.java create mode 100644 src/main/java/mouamle/tggh/common/Settings.java create mode 100644 src/main/java/mouamle/tggh/common/Tokens.java create mode 100644 src/main/java/mouamle/tggh/github/GithubInterface.java create mode 100644 src/main/java/mouamle/tggh/github/service/GithubService.java create mode 100644 src/main/java/mouamle/tggh/github/web/IssuesEndpoint.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/Assignee.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/Changes.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/Creator.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/Issue.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/IssueEvent.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/Label.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/License.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/Milestone.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/Owner.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/Repository.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/Sender.java create mode 100644 src/main/java/mouamle/tggh/github/web/model/User.java create mode 100644 src/main/java/mouamle/tggh/github/web/service/IssuesBus.java create mode 100644 src/main/java/mouamle/tggh/github/web/service/PayloadRegistry.java create mode 100644 src/main/java/mouamle/tggh/telegram/TelegramInterface.java create mode 100644 src/main/java/mouamle/tggh/telegram/bot/IssueTrackerBot.java create mode 100644 src/main/java/mouamle/tggh/telegram/bot/service/IssueHookHandler.java create mode 100644 src/main/java/mouamle/tggh/util/bus/AbstractEventBus.java create mode 100644 src/main/java/mouamle/tggh/util/bus/EventBus.java diff --git a/src/main/java/mouamle/tggh/Application.java b/src/main/java/mouamle/tggh/Application.java index fc02d8e..b60cb59 100644 --- a/src/main/java/mouamle/tggh/Application.java +++ b/src/main/java/mouamle/tggh/Application.java @@ -1,7 +1,11 @@ package mouamle.tggh; +import mouamle.tggh.common.ServiceInterface; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; @SpringBootApplication public class Application { @@ -10,4 +14,12 @@ public static void main(String[] args) { SpringApplication.run(Application.class); } + @Bean + ApplicationRunner init(@Qualifier("githubInterface") ServiceInterface githubInterface, + @Qualifier("telegramInterface") ServiceInterface telegramInterface) { + return args -> { + githubInterface.init(); + telegramInterface.init(); + }; + } } diff --git a/src/main/java/mouamle/tggh/common/ServiceInterface.java b/src/main/java/mouamle/tggh/common/ServiceInterface.java new file mode 100644 index 0000000..471b5d0 --- /dev/null +++ b/src/main/java/mouamle/tggh/common/ServiceInterface.java @@ -0,0 +1,5 @@ +package mouamle.tggh.common; + +public interface ServiceInterface { + void init(); +} diff --git a/src/main/java/mouamle/tggh/common/Settings.java b/src/main/java/mouamle/tggh/common/Settings.java new file mode 100644 index 0000000..b5b4a9d --- /dev/null +++ b/src/main/java/mouamle/tggh/common/Settings.java @@ -0,0 +1,33 @@ +package mouamle.tggh.common; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class Settings { + + private final String botUsername; + private final int creatorId; + private final long groupId; + + public Settings(@Value("${app.telegram-username}") String botUsername, + @Value("${app.telegram-creatorId}") int creatorId, + @Value("${app.telegram-groupId}") long groupId) { + this.botUsername = botUsername; + this.creatorId = creatorId; + this.groupId = groupId; + } + + public String getBotUsername() { + return botUsername; + } + + public int getCreatorId() { + return creatorId; + } + + public long getGroupId() { + return groupId; + } + +} diff --git a/src/main/java/mouamle/tggh/common/Tokens.java b/src/main/java/mouamle/tggh/common/Tokens.java new file mode 100644 index 0000000..3f276bb --- /dev/null +++ b/src/main/java/mouamle/tggh/common/Tokens.java @@ -0,0 +1,27 @@ +package mouamle.tggh.common; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class Tokens { + + private final String telegramToken; + private final String githubToken; + + public Tokens(@Value("${app.telegram-token}") String telegramToken, + @Value("${app.github-token}") String githubToken) { + this.telegramToken = telegramToken; + this.githubToken = githubToken; + } + + + public String getTelegramToken() { + return telegramToken; + } + + public String getGithubToken() { + return githubToken; + } + +} diff --git a/src/main/java/mouamle/tggh/github/GithubInterface.java b/src/main/java/mouamle/tggh/github/GithubInterface.java new file mode 100644 index 0000000..c6a3463 --- /dev/null +++ b/src/main/java/mouamle/tggh/github/GithubInterface.java @@ -0,0 +1,12 @@ +package mouamle.tggh.github; + +import mouamle.tggh.common.ServiceInterface; +import org.springframework.stereotype.Service; + +@Service +public class GithubInterface implements ServiceInterface { + + @Override + public void init() { /*TODO*/ } + +} diff --git a/src/main/java/mouamle/tggh/github/service/GithubService.java b/src/main/java/mouamle/tggh/github/service/GithubService.java new file mode 100644 index 0000000..3f568d1 --- /dev/null +++ b/src/main/java/mouamle/tggh/github/service/GithubService.java @@ -0,0 +1,30 @@ +package mouamle.tggh.github.service; + +import mouamle.tggh.common.Tokens; +import org.eclipse.egit.github.core.User; +import org.eclipse.egit.github.core.client.GitHubClient; +import org.eclipse.egit.github.core.service.UserService; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +public class GithubService { + + private GitHubClient client; + + public GithubService(Tokens tokens) { + client = new GitHubClient(); + client.setOAuth2Token(tokens.getGithubToken()); + } + + public GitHubClient getClient() { + return client; + } + + public User getUser(String name) throws IOException { + UserService service = new UserService(client); + return service.getUser(name); + } + +} diff --git a/src/main/java/mouamle/tggh/github/web/IssuesEndpoint.java b/src/main/java/mouamle/tggh/github/web/IssuesEndpoint.java new file mode 100644 index 0000000..51216ec --- /dev/null +++ b/src/main/java/mouamle/tggh/github/web/IssuesEndpoint.java @@ -0,0 +1,52 @@ +package mouamle.tggh.github.web; + +import mouamle.tggh.github.web.model.IssueEvent; +import mouamle.tggh.github.web.service.PayloadRegistry; +import mouamle.tggh.util.bus.EventBus; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; + +@RestController +public class IssuesEndpoint { + + private final EventBus bus; + private final PayloadRegistry payloadRegistry; + + @Autowired + public IssuesEndpoint(EventBus bus, PayloadRegistry payloadRegistry) { + this.payloadRegistry = payloadRegistry; + this.bus = bus; + } + + @PostMapping("hook") + public void hook(@RequestBody String payload, + @RequestHeader("X-Hub-Signature") String signature, + @RequestHeader("X-Github-Event") String event) throws IOException { + + validateSignature(signature); + payloadRegistry.process(event, payload, bus::publish); + } + + private void validateSignature(String signature) { + if (!signature.trim().isEmpty()) { + String[] split = signature.split("="); + if (split.length == 2) { + String hash = split[1]; + if (isValidSHA1(hash)) { + return; + } + } + } + throw new RuntimeException("Nope!"); + } + + private boolean isValidSHA1(String s) { + return s.matches("^[a-fA-F0-9]{40}$"); + } + +} diff --git a/src/main/java/mouamle/tggh/github/web/model/Assignee.java b/src/main/java/mouamle/tggh/github/web/model/Assignee.java new file mode 100644 index 0000000..36b0bc5 --- /dev/null +++ b/src/main/java/mouamle/tggh/github/web/model/Assignee.java @@ -0,0 +1,217 @@ +package mouamle.tggh.github.web.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.io.Serializable; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "login", + "id", + "node_id", + "avatar_url", + "gravatar_id", + "url", + "html_url", + "followers_url", + "following_url", + "gists_url", + "starred_url", + "subscriptions_url", + "organizations_url", + "repos_url", + "events_url", + "received_events_url", + "type", + "site_admin" +}) +public class Assignee implements Serializable { + + private final static long serialVersionUID = 7821579502649398611L; + @JsonProperty("login") + public String login; + @JsonProperty("id") + public int id; + @JsonProperty("node_id") + public String nodeId; + @JsonProperty("avatar_url") + public String avatarUrl; + @JsonProperty("gravatar_id") + public String gravatarId; + @JsonProperty("url") + public String url; + @JsonProperty("html_url") + public String htmlUrl; + @JsonProperty("followers_url") + public String followersUrl; + @JsonProperty("following_url") + public String followingUrl; + @JsonProperty("gists_url") + public String gistsUrl; + @JsonProperty("starred_url") + public String starredUrl; + @JsonProperty("subscriptions_url") + public String subscriptionsUrl; + @JsonProperty("organizations_url") + public String organizationsUrl; + @JsonProperty("repos_url") + public String reposUrl; + @JsonProperty("events_url") + public String eventsUrl; + @JsonProperty("received_events_url") + public String receivedEventsUrl; + @JsonProperty("type") + public String type; + @JsonProperty("site_admin") + public boolean siteAdmin; + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public String getAvatarUrl() { + return avatarUrl; + } + + public void setAvatarUrl(String avatarUrl) { + this.avatarUrl = avatarUrl; + } + + public String getGravatarId() { + return gravatarId; + } + + public void setGravatarId(String gravatarId) { + this.gravatarId = gravatarId; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getHtmlUrl() { + return htmlUrl; + } + + public void setHtmlUrl(String htmlUrl) { + this.htmlUrl = htmlUrl; + } + + public String getFollowersUrl() { + return followersUrl; + } + + public void setFollowersUrl(String followersUrl) { + this.followersUrl = followersUrl; + } + + public String getFollowingUrl() { + return followingUrl; + } + + public void setFollowingUrl(String followingUrl) { + this.followingUrl = followingUrl; + } + + public String getGistsUrl() { + return gistsUrl; + } + + public void setGistsUrl(String gistsUrl) { + this.gistsUrl = gistsUrl; + } + + public String getStarredUrl() { + return starredUrl; + } + + public void setStarredUrl(String starredUrl) { + this.starredUrl = starredUrl; + } + + public String getSubscriptionsUrl() { + return subscriptionsUrl; + } + + public void setSubscriptionsUrl(String subscriptionsUrl) { + this.subscriptionsUrl = subscriptionsUrl; + } + + public String getOrganizationsUrl() { + return organizationsUrl; + } + + public void setOrganizationsUrl(String organizationsUrl) { + this.organizationsUrl = organizationsUrl; + } + + public String getReposUrl() { + return reposUrl; + } + + public void setReposUrl(String reposUrl) { + this.reposUrl = reposUrl; + } + + public String getEventsUrl() { + return eventsUrl; + } + + public void setEventsUrl(String eventsUrl) { + this.eventsUrl = eventsUrl; + } + + public String getReceivedEventsUrl() { + return receivedEventsUrl; + } + + public void setReceivedEventsUrl(String receivedEventsUrl) { + this.receivedEventsUrl = receivedEventsUrl; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public boolean isSiteAdmin() { + return siteAdmin; + } + + public void setSiteAdmin(boolean siteAdmin) { + this.siteAdmin = siteAdmin; + } +} diff --git a/src/main/java/mouamle/tggh/github/web/model/Changes.java b/src/main/java/mouamle/tggh/github/web/model/Changes.java new file mode 100644 index 0000000..def6e69 --- /dev/null +++ b/src/main/java/mouamle/tggh/github/web/model/Changes.java @@ -0,0 +1,16 @@ +package mouamle.tggh.github.web.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.io.Serializable; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + +}) +public class Changes implements Serializable { + + private final static long serialVersionUID = 7689728567094940902L; + +} diff --git a/src/main/java/mouamle/tggh/github/web/model/Creator.java b/src/main/java/mouamle/tggh/github/web/model/Creator.java new file mode 100644 index 0000000..f625214 --- /dev/null +++ b/src/main/java/mouamle/tggh/github/web/model/Creator.java @@ -0,0 +1,217 @@ +package mouamle.tggh.github.web.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.io.Serializable; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "login", + "id", + "node_id", + "avatar_url", + "gravatar_id", + "url", + "html_url", + "followers_url", + "following_url", + "gists_url", + "starred_url", + "subscriptions_url", + "organizations_url", + "repos_url", + "events_url", + "received_events_url", + "type", + "site_admin" +}) +public class Creator implements Serializable { + + private final static long serialVersionUID = -3988921471796772482L; + @JsonProperty("login") + public String login; + @JsonProperty("id") + public int id; + @JsonProperty("node_id") + public String nodeId; + @JsonProperty("avatar_url") + public String avatarUrl; + @JsonProperty("gravatar_id") + public String gravatarId; + @JsonProperty("url") + public String url; + @JsonProperty("html_url") + public String htmlUrl; + @JsonProperty("followers_url") + public String followersUrl; + @JsonProperty("following_url") + public String followingUrl; + @JsonProperty("gists_url") + public String gistsUrl; + @JsonProperty("starred_url") + public String starredUrl; + @JsonProperty("subscriptions_url") + public String subscriptionsUrl; + @JsonProperty("organizations_url") + public String organizationsUrl; + @JsonProperty("repos_url") + public String reposUrl; + @JsonProperty("events_url") + public String eventsUrl; + @JsonProperty("received_events_url") + public String receivedEventsUrl; + @JsonProperty("type") + public String type; + @JsonProperty("site_admin") + public boolean siteAdmin; + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public String getAvatarUrl() { + return avatarUrl; + } + + public void setAvatarUrl(String avatarUrl) { + this.avatarUrl = avatarUrl; + } + + public String getGravatarId() { + return gravatarId; + } + + public void setGravatarId(String gravatarId) { + this.gravatarId = gravatarId; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getHtmlUrl() { + return htmlUrl; + } + + public void setHtmlUrl(String htmlUrl) { + this.htmlUrl = htmlUrl; + } + + public String getFollowersUrl() { + return followersUrl; + } + + public void setFollowersUrl(String followersUrl) { + this.followersUrl = followersUrl; + } + + public String getFollowingUrl() { + return followingUrl; + } + + public void setFollowingUrl(String followingUrl) { + this.followingUrl = followingUrl; + } + + public String getGistsUrl() { + return gistsUrl; + } + + public void setGistsUrl(String gistsUrl) { + this.gistsUrl = gistsUrl; + } + + public String getStarredUrl() { + return starredUrl; + } + + public void setStarredUrl(String starredUrl) { + this.starredUrl = starredUrl; + } + + public String getSubscriptionsUrl() { + return subscriptionsUrl; + } + + public void setSubscriptionsUrl(String subscriptionsUrl) { + this.subscriptionsUrl = subscriptionsUrl; + } + + public String getOrganizationsUrl() { + return organizationsUrl; + } + + public void setOrganizationsUrl(String organizationsUrl) { + this.organizationsUrl = organizationsUrl; + } + + public String getReposUrl() { + return reposUrl; + } + + public void setReposUrl(String reposUrl) { + this.reposUrl = reposUrl; + } + + public String getEventsUrl() { + return eventsUrl; + } + + public void setEventsUrl(String eventsUrl) { + this.eventsUrl = eventsUrl; + } + + public String getReceivedEventsUrl() { + return receivedEventsUrl; + } + + public void setReceivedEventsUrl(String receivedEventsUrl) { + this.receivedEventsUrl = receivedEventsUrl; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public boolean isSiteAdmin() { + return siteAdmin; + } + + public void setSiteAdmin(boolean siteAdmin) { + this.siteAdmin = siteAdmin; + } +} diff --git a/src/main/java/mouamle/tggh/github/web/model/Issue.java b/src/main/java/mouamle/tggh/github/web/model/Issue.java new file mode 100644 index 0000000..24a652a --- /dev/null +++ b/src/main/java/mouamle/tggh/github/web/model/Issue.java @@ -0,0 +1,302 @@ +package mouamle.tggh.github.web.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import java.io.Serializable; +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ + "url", + "repository_url", + "labels_url", + "comments_url", + "events_url", + "html_url", + "id", + "node_id", + "number", + "title", + "user", + "labels", + "state", + "locked", + "assignee", + "assignees", + "milestone", + "comments", + "created_at", + "updated_at", + "closed_at", + "author_association", + "body" +}) +public class Issue implements Serializable { + + private final static long serialVersionUID = -7561304827206118591L; + @JsonProperty("url") + public String url; + @JsonProperty("repository_url") + public String repositoryUrl; + @JsonProperty("labels_url") + public String labelsUrl; + @JsonProperty("comments_url") + public String commentsUrl; + @JsonProperty("events_url") + public String eventsUrl; + @JsonProperty("html_url") + public String htmlUrl; + @JsonProperty("id") + public Integer id; + @JsonProperty("node_id") + public String nodeId; + @JsonProperty("number") + public Integer number; + @JsonProperty("title") + public String title; + @JsonProperty("user") + public User user; + @JsonProperty("labels") + public List