Add pull request and repository browsing
This commit is contained in:
156
crates/app/src/activity.rs
Normal file
156
crates/app/src/activity.rs
Normal file
@@ -0,0 +1,156 @@
|
||||
use gotcha_gitea::models;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum Target {
|
||||
Commit {
|
||||
owner: String,
|
||||
repository: String,
|
||||
sha: String,
|
||||
},
|
||||
Issue {
|
||||
owner: String,
|
||||
repository: String,
|
||||
number: i64,
|
||||
},
|
||||
Pull {
|
||||
owner: String,
|
||||
repository: String,
|
||||
number: i64,
|
||||
},
|
||||
}
|
||||
|
||||
pub fn target(activity: &models::Activity) -> Option<Target> {
|
||||
use models::activity::OpType;
|
||||
|
||||
let (owner, repository) = activity
|
||||
.repo
|
||||
.as_ref()?
|
||||
.full_name
|
||||
.as_deref()?
|
||||
.split_once('/')?;
|
||||
let pair = || (owner.to_string(), repository.to_string());
|
||||
match activity.op_type? {
|
||||
OpType::CommitRepo | OpType::MirrorSyncPush => {
|
||||
let (owner, repository) = pair();
|
||||
Some(Target::Commit {
|
||||
owner,
|
||||
repository,
|
||||
sha: commit_sha(activity.content.as_deref()?)?,
|
||||
})
|
||||
}
|
||||
OpType::CreateIssue | OpType::CloseIssue | OpType::ReopenIssue | OpType::CommentIssue => {
|
||||
let (owner, repository) = pair();
|
||||
Some(Target::Issue {
|
||||
owner,
|
||||
repository,
|
||||
number: issue_number(activity)?,
|
||||
})
|
||||
}
|
||||
OpType::CreatePullRequest
|
||||
| OpType::MergePullRequest
|
||||
| OpType::AutoMergePullRequest
|
||||
| OpType::ClosePullRequest
|
||||
| OpType::ReopenPullRequest
|
||||
| OpType::CommentPull
|
||||
| OpType::ApprovePullRequest
|
||||
| OpType::RejectPullRequest
|
||||
| OpType::PullReviewDismissed
|
||||
| OpType::PullRequestReadyForReview => {
|
||||
let (owner, repository) = pair();
|
||||
Some(Target::Pull {
|
||||
owner,
|
||||
repository,
|
||||
number: issue_number(activity)?,
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn issue_number(activity: &models::Activity) -> Option<i64> {
|
||||
activity
|
||||
.comment
|
||||
.as_ref()
|
||||
.and_then(|comment| {
|
||||
comment
|
||||
.pull_request_url
|
||||
.as_deref()
|
||||
.or(comment.issue_url.as_deref())
|
||||
})
|
||||
.and_then(url_number)
|
||||
.or_else(|| {
|
||||
activity
|
||||
.content
|
||||
.as_deref()?
|
||||
.split(|character: char| !character.is_ascii_digit())
|
||||
.find(|part| !part.is_empty())?
|
||||
.parse()
|
||||
.ok()
|
||||
})
|
||||
}
|
||||
|
||||
fn url_number(url: &str) -> Option<i64> {
|
||||
url.trim_end_matches('/').rsplit('/').next()?.parse().ok()
|
||||
}
|
||||
|
||||
fn commit_sha(content: &str) -> Option<String> {
|
||||
let payload: serde_json::Value = serde_json::from_str(content).ok()?;
|
||||
payload.get("HeadCommit").and_then(find_sha).or_else(|| {
|
||||
payload
|
||||
.get("Commits")?
|
||||
.as_array()?
|
||||
.last()
|
||||
.and_then(find_sha)
|
||||
})
|
||||
}
|
||||
|
||||
fn find_sha(value: &serde_json::Value) -> Option<String> {
|
||||
value.as_object()?.iter().find_map(|(key, value)| {
|
||||
(key.to_ascii_lowercase().contains("sha"))
|
||||
.then(|| value.as_str())
|
||||
.flatten()
|
||||
.filter(|sha| sha.len() >= 7)
|
||||
.map(str::to_string)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use models::activity::OpType;
|
||||
|
||||
fn activity(op_type: OpType, content: &str) -> models::Activity {
|
||||
models::Activity {
|
||||
op_type: Some(op_type),
|
||||
content: Some(content.into()),
|
||||
repo: Some(Box::new(models::Repository {
|
||||
full_name: Some("octo/demo".into()),
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decodes_linkable_activity_targets() {
|
||||
assert_eq!(
|
||||
target(&activity(OpType::CreatePullRequest, "42|feature")),
|
||||
Some(Target::Pull {
|
||||
owner: "octo".into(),
|
||||
repository: "demo".into(),
|
||||
number: 42,
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
target(&activity(
|
||||
OpType::CommitRepo,
|
||||
r#"{"HeadCommit":{"Sha1":"0123456789abcdef"}}"#,
|
||||
)),
|
||||
Some(Target::Commit {
|
||||
owner: "octo".into(),
|
||||
repository: "demo".into(),
|
||||
sha: "0123456789abcdef".into(),
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user