mirror of
https://github.com/sern-handler/automata
synced 2026-06-06 01:16:51 +00:00
feat: can create pull requests now :D
This commit is contained in:
124
.idea/uiDesigner.xml
generated
Normal file
124
.idea/uiDesigner.xml
generated
Normal file
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,80 +1,76 @@
|
||||
import io.github.cdimascio.dotenv.dotenv
|
||||
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.engine.*
|
||||
import io.ktor.server.netty.*
|
||||
import io.ktor.server.plugins.contentnegotiation.*
|
||||
import jdk.nashorn.internal.parser.Token
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import structures.HttpProvider
|
||||
import structures.api.Response
|
||||
import structures.api.account.OrgAccount
|
||||
import structures.api.account.TokenData
|
||||
import java.util.*
|
||||
import structures.wrapped.Base
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
object Globals {
|
||||
val eventEmitter = EventEmitter<Base>()
|
||||
val serializer = Json {
|
||||
ignoreUnknownKeys = true
|
||||
prettyPrint = true
|
||||
explicitNulls = false
|
||||
}
|
||||
}
|
||||
|
||||
object Client : CoroutineScope {
|
||||
|
||||
class Client : CoroutineScope {
|
||||
val api = HttpProvider(this)
|
||||
private var parentJob = Job()
|
||||
val eventEmitter = EventEmitter()
|
||||
val json = Json { ignoreUnknownKeys = true }
|
||||
lateinit var application : structures.api.application.Application
|
||||
lateinit var orgAccount: OrgAccount
|
||||
lateinit var tokenData : TokenData
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = Dispatchers.Default + parentJob
|
||||
private val server = embeddedServer(
|
||||
Netty,
|
||||
port = 8000,
|
||||
host = "localhost",
|
||||
parentCoroutineContext = coroutineContext
|
||||
) {
|
||||
configureRouting()
|
||||
install(ContentNegotiation)
|
||||
}
|
||||
init {
|
||||
dotenv {
|
||||
systemProperties = true
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T : Response> on(
|
||||
inline fun <reified T : Base> on(
|
||||
eventName: String,
|
||||
crossinline fn: (T) -> Unit
|
||||
crossinline fn: suspend (T) -> Unit
|
||||
) {
|
||||
launch {
|
||||
eventEmitter.events.collect {
|
||||
Globals.eventEmitter.events.collect {
|
||||
when (eventName) {
|
||||
"pull_request" -> {
|
||||
fn(json.decodeFromString(it))
|
||||
fn(it as T)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
suspend fun loginAsync() {
|
||||
verifyWithJwt()
|
||||
verifyWithInstallationApp()
|
||||
getInstallationToken()
|
||||
|
||||
}
|
||||
private suspend fun verifyWithJwt() {
|
||||
application = HttpProvider.loginIntoApplicationAsync().await()
|
||||
}
|
||||
private suspend fun verifyWithInstallationApp() {
|
||||
orgAccount = HttpProvider.loginIntoOrgAsync().await()
|
||||
|
||||
}
|
||||
private suspend fun getInstallationToken() {
|
||||
tokenData = HttpProvider.getInstallationToken(orgAccount).await()
|
||||
coroutineScope {
|
||||
withContext(Dispatchers.Default) {
|
||||
application = api.loginIntoApplicationAsync().await()
|
||||
orgAccount = api.loginIntoOrgAsync().await()
|
||||
tokenData = api.getInstallationTokenAsync(orgAccount).await()
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This should start last in order to prevent blocking of thread and listeners
|
||||
*/
|
||||
fun startWebhookListener() {
|
||||
server.start(wait = true)
|
||||
embeddedServer(
|
||||
Netty,
|
||||
port = 8000,
|
||||
host = "localhost",
|
||||
parentCoroutineContext = coroutineContext
|
||||
) {
|
||||
configureRouting(this@Client)
|
||||
install(ContentNegotiation) {
|
||||
json(Globals.serializer)
|
||||
}
|
||||
}.start(wait = true).also { println("Started server") }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import structures.api.Response
|
||||
import structures.wrapped.Base
|
||||
|
||||
class EventEmitter {
|
||||
private val _events = MutableSharedFlow<String>() // private mutable shared flow
|
||||
class EventEmitter<T : Base> {
|
||||
private val _events = MutableSharedFlow<T>() // private mutable shared flow
|
||||
val events = _events.asSharedFlow() // publicly exposed as read-only shared flow
|
||||
|
||||
suspend fun produceEvent(event: String) {
|
||||
suspend fun produceEvent(event: T) {
|
||||
_events.emit(event) // suspends until all subscribers receive it
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,49 @@
|
||||
import HashUtils.verifySignature
|
||||
import arrow.core.Either
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.util.pipeline.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.InputStreamReader
|
||||
import java.io.Reader
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import javax.crypto.Mac
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
import kotlin.experimental.xor
|
||||
|
||||
|
||||
fun Application.configureRouting() {
|
||||
fun Application.configureRouting(client: Client) {
|
||||
routing {
|
||||
pullRequests()
|
||||
|
||||
pullRequests(client)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun Routing.pullRequests() {
|
||||
fun Routing.pullRequests(client: Client) {
|
||||
post("/pulls") {
|
||||
val secret = call.request.headers["X-Hub-Signature-256"]!!
|
||||
val text = call.receiveText()
|
||||
if(!HashUtils.secureCompare(secret, HashUtils.sha256(text))) {
|
||||
call.respond(HttpStatusCode.Unauthorized, "Nice try")
|
||||
val event = call.request.headers["X-Github-Event"]!!
|
||||
val respText = call.receiveText()
|
||||
when(val resp = verifySignature(secret, respText)) {
|
||||
is Either.Left -> {
|
||||
launch(Dispatchers.Default) {
|
||||
when(event) {
|
||||
"pull_request" -> {
|
||||
Globals.eventEmitter.produceEvent(
|
||||
structures.wrapped.PullRequestsManager(client,
|
||||
Globals.serializer.decodeFromString(resp.value)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
call.respond(HttpStatusCode.OK)
|
||||
}.join()
|
||||
}
|
||||
is Either.Right -> resp.value
|
||||
}
|
||||
launch(Dispatchers.Default) {
|
||||
Client.eventEmitter.produceEvent(text)
|
||||
}.join()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,4 +78,11 @@ object HashUtils {
|
||||
val hash: ByteArray = hasher.doFinal(body.toByteArray())
|
||||
return "sha256=${hash.toHex()}"
|
||||
}
|
||||
|
||||
suspend inline fun PipelineContext<Unit, ApplicationCall>.verifySignature(secret: String, resp: String) : Either<String, Unit> {
|
||||
if(secureCompare(secret, sha256(resp))) {
|
||||
return Either.Left(resp)
|
||||
}
|
||||
return Either.Right(call.respond(HttpStatusCode.Unauthorized, "Nice try"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import structures.api.PullRequests
|
||||
import structures.api.application.PullRequestAction
|
||||
import structures.options.PullRequestCreateOptions
|
||||
import structures.wrapped.PullRequestsManager
|
||||
|
||||
fun main() = runBlocking {
|
||||
val sernClient = Client()
|
||||
sernClient.loginAsync()
|
||||
|
||||
|
||||
Client.loginAsync()
|
||||
println(Client.orgAccount)
|
||||
Client.on<PullRequests>("pull_request") { pr_event ->
|
||||
println(pr_event)
|
||||
sernClient.on<PullRequestsManager>("pull_request") { pr_event ->
|
||||
when(pr_event.action) {
|
||||
PullRequestAction.Opened -> {
|
||||
println("new pull request opened")
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
Client.startWebhookListener()
|
||||
sernClient.startWebhookListener()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package structures
|
||||
|
||||
import Client
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.engine.cio.*
|
||||
@@ -9,29 +9,53 @@ import io.ktor.client.statement.*
|
||||
import io.ktor.http.*
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.encodeToString
|
||||
import structures.api.Response
|
||||
import structures.api.account.OrgAccount
|
||||
import structures.api.account.TokenData
|
||||
import structures.api.application.Application
|
||||
import structures.options.PostOptions
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
object HttpProvider : CoroutineScope {
|
||||
private val httpClient = HttpClient(CIO) {
|
||||
class HttpProvider(private val client: Client) : CoroutineScope {
|
||||
val httpClient = HttpClient(CIO) {
|
||||
install(ContentNegotiation) {
|
||||
json(Json {
|
||||
prettyPrint = true
|
||||
})
|
||||
json(Globals.serializer)
|
||||
}
|
||||
}
|
||||
enum class ApiType {
|
||||
Rest,
|
||||
App
|
||||
}
|
||||
val orgName = "sern-handler"
|
||||
val baseLink = "https://api.github.com"
|
||||
|
||||
fun authHeader(type: ApiType): Pair<String, String> {
|
||||
return HttpHeaders.Authorization to when(type) {
|
||||
ApiType.App -> "Bearer ${JWTProvider.jwt}"
|
||||
ApiType.Rest -> "Bearer ${client.tokenData.token}"
|
||||
}
|
||||
}
|
||||
val contentTypeHeader = HttpHeaders.Accept to "application/vnd.github+json"
|
||||
inline fun <reified T : Response, reified V: PostOptions> postAsync(path: String, body: V) : Deferred<T> {
|
||||
return async {
|
||||
httpClient.post("$baseLink/$path") {
|
||||
headers {
|
||||
append(HttpHeaders.ContentType, "application/json")
|
||||
append(contentTypeHeader)
|
||||
append(authHeader(ApiType.Rest))
|
||||
}
|
||||
setBody(body)
|
||||
}.body()
|
||||
}
|
||||
}
|
||||
private const val orgName = "sern-handler"
|
||||
private const val baseLink = "https://api.github.com"
|
||||
|
||||
fun loginIntoApplicationAsync() : Deferred<Application> {
|
||||
return async {
|
||||
httpClient.request("$baseLink/app") {
|
||||
headers {
|
||||
append(HttpHeaders.Accept, "application/vnd.github+json")
|
||||
append(HttpHeaders.Authorization, "Bearer ${JWTProvider.jwt}")
|
||||
append(contentTypeHeader)
|
||||
append(authHeader(ApiType.App))
|
||||
}
|
||||
}.body()
|
||||
}
|
||||
@@ -41,23 +65,27 @@ object HttpProvider : CoroutineScope {
|
||||
// GHAppInstallation
|
||||
httpClient.request("$baseLink/orgs/$orgName/installation") {
|
||||
headers {
|
||||
append(HttpHeaders.Accept, "application/vnd.github+json")
|
||||
append(HttpHeaders.Authorization, "Bearer ${JWTProvider.jwt}")
|
||||
append(contentTypeHeader)
|
||||
append(authHeader(ApiType.App))
|
||||
}
|
||||
}.body()
|
||||
}
|
||||
}
|
||||
|
||||
fun getInstallationToken(orgAccount: OrgAccount): Deferred<TokenData> {
|
||||
fun getInstallationTokenAsync(orgAccount: OrgAccount): Deferred<TokenData> {
|
||||
return async {
|
||||
httpClient.post("$baseLink/app/installations/${orgAccount.id}/access_tokens") {
|
||||
headers {
|
||||
append(HttpHeaders.Accept, "application/vnd.github+json")
|
||||
append(HttpHeaders.Authorization, "Bearer ${JWTProvider.jwt}")
|
||||
append(contentTypeHeader)
|
||||
append(authHeader(ApiType.App))
|
||||
}
|
||||
}.body()
|
||||
}
|
||||
}
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = Dispatchers.Default + Job()
|
||||
}
|
||||
}
|
||||
|
||||
fun HeadersBuilder.append(name: Pair<String, String>) {
|
||||
append(name.first, name.second)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ data class PullRequest(
|
||||
val labels: List<Label>,
|
||||
val locked: Boolean,
|
||||
val maintainer_can_modify: Boolean,
|
||||
val merge_commit_sha: String,
|
||||
val merge_commit_sha: String?,
|
||||
val mergeable: Boolean?,
|
||||
val mergeable_state: String,
|
||||
val merged: Boolean,
|
||||
@@ -51,7 +51,7 @@ data class PullRequest(
|
||||
val updated_at: String,
|
||||
val url: String,
|
||||
val user: User
|
||||
)
|
||||
) : Response()
|
||||
|
||||
@kotlinx.serialization.Serializable
|
||||
data class MergedBy(
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package structures.api
|
||||
@kotlinx.serialization.Serializable
|
||||
data class Repo(
|
||||
val allow_auto_merge: Boolean,
|
||||
val allow_auto_merge: Boolean?,
|
||||
val allow_forking: Boolean,
|
||||
val allow_merge_commit: Boolean,
|
||||
val allow_rebase_merge: Boolean,
|
||||
val allow_squash_merge: Boolean,
|
||||
val allow_update_branch: Boolean,
|
||||
val allow_merge_commit: Boolean?,
|
||||
val allow_rebase_merge: Boolean?,
|
||||
val allow_squash_merge: Boolean?,
|
||||
val allow_update_branch: Boolean?,
|
||||
val archive_url: String,
|
||||
val archived: Boolean,
|
||||
val assignees_url: String,
|
||||
@@ -21,7 +21,7 @@ data class Repo(
|
||||
val contributors_url: String,
|
||||
val created_at: String,
|
||||
val default_branch: String,
|
||||
val delete_branch_on_merge: Boolean,
|
||||
val delete_branch_on_merge: Boolean?,
|
||||
val deployments_url: String,
|
||||
val description: String,
|
||||
val disabled: Boolean,
|
||||
@@ -41,7 +41,7 @@ data class Repo(
|
||||
val has_pages: Boolean,
|
||||
val has_projects: Boolean,
|
||||
val has_wiki: Boolean,
|
||||
val homepage: String,
|
||||
val homepage: String?,
|
||||
val hooks_url: String,
|
||||
val html_url: String,
|
||||
val id: Int,
|
||||
@@ -51,11 +51,11 @@ data class Repo(
|
||||
val issues_url: String,
|
||||
val keys_url: String,
|
||||
val labels_url: String,
|
||||
val language: String,
|
||||
val language: String?,
|
||||
val languages_url: String,
|
||||
val license: String?,
|
||||
val merge_commit_message: String,
|
||||
val merge_commit_title: String,
|
||||
val merge_commit_message: String?,
|
||||
val merge_commit_title: String?,
|
||||
val merges_url: String,
|
||||
val milestones_url: String,
|
||||
val mirror_url: String?,
|
||||
@@ -70,8 +70,8 @@ data class Repo(
|
||||
val pushed_at: String,
|
||||
val releases_url: String,
|
||||
val size: Int,
|
||||
val squash_merge_commit_message: String,
|
||||
val squash_merge_commit_title: String,
|
||||
val squash_merge_commit_message: String?,
|
||||
val squash_merge_commit_title: String?,
|
||||
val ssh_url: String,
|
||||
val stargazers_count: Int,
|
||||
val stargazers_url: String,
|
||||
@@ -85,7 +85,7 @@ data class Repo(
|
||||
val trees_url: String,
|
||||
val updated_at: String,
|
||||
val url: String,
|
||||
val use_squash_pr_title_as_default: Boolean,
|
||||
val use_squash_pr_title_as_default: Boolean?,
|
||||
val visibility: String,
|
||||
val watchers: Int,
|
||||
val watchers_count: Int,
|
||||
|
||||
@@ -3,4 +3,4 @@ package structures.api
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
sealed class Response
|
||||
sealed class Response
|
||||
|
||||
5
src/main/kotlin/structures/wrapped/Base.kt
Normal file
5
src/main/kotlin/structures/wrapped/Base.kt
Normal file
@@ -0,0 +1,5 @@
|
||||
package structures.wrapped
|
||||
|
||||
import Client
|
||||
|
||||
open class Base(val client: Client)
|
||||
@@ -1,11 +0,0 @@
|
||||
package structures.wrapped
|
||||
|
||||
|
||||
class PullRequests(
|
||||
private val prs: structures.api.PullRequests
|
||||
) {
|
||||
val action = prs.action
|
||||
val head = prs.pull_request.head
|
||||
val base = prs.pull_request.base
|
||||
val currentRepository = Repository(prs.repository)
|
||||
}
|
||||
26
src/main/kotlin/structures/wrapped/PullRequestsManager.kt
Normal file
26
src/main/kotlin/structures/wrapped/PullRequestsManager.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
package structures.wrapped
|
||||
|
||||
import Client
|
||||
import kotlinx.coroutines.Deferred
|
||||
import structures.api.PullRequest
|
||||
import structures.options.PullRequestCreateOptions
|
||||
import structures.api.PullRequests
|
||||
|
||||
|
||||
|
||||
class PullRequestsManager(
|
||||
client: Client,
|
||||
private val prs: PullRequests
|
||||
) : Base(client) {
|
||||
val action = prs.action
|
||||
val head = prs.pull_request.head
|
||||
val base = prs.pull_request.base
|
||||
val currentRepository = Repository(client, prs.repository)
|
||||
|
||||
fun create(
|
||||
repoName: String,
|
||||
options: PullRequestCreateOptions
|
||||
): Deferred<PullRequest> {
|
||||
return client.api.postAsync("repos/${client.api.orgName}/${repoName}/pulls", options)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,13 @@
|
||||
package structures.wrapped
|
||||
|
||||
import Client
|
||||
import structures.api.Repository
|
||||
|
||||
class Repository(
|
||||
repository: structures.api.Repository
|
||||
) {
|
||||
client: Client,
|
||||
repository: Repository
|
||||
) : Base(client) {
|
||||
val name = repository.name
|
||||
val fullName = repository.full_name
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user