|
- use std::env;
- use std::str::FromStr;
-
- extern crate serenity;
- use serenity::{
- model::channel::Message,
- //model::channel::Attachment,
- prelude::*,
- utils::MessageBuilder,
- utils::Colour,
- };
-
- extern crate regex;
- use regex::{Regex, RegexBuilder};
-
- extern crate swagger;
- use swagger::apis;
- //use swagger::apis::RepositoryApi;
-
- extern crate hyper;
- use hyper::{Client, Uri};
-
- extern crate hyper_tls;
- use hyper_tls::HttpsConnector;
-
- extern crate tokio_core;
- use tokio_core::reactor::Core;
-
- extern crate futures;
- use futures::prelude::Future;
-
- use crate::traits::Command;
-
- pub struct CmdGitea {
- format: Regex,
- help_format: Regex,
- }
-
- impl Command for CmdGitea {
- fn execute(&mut self, ctx: &Context, msg: &Message) {
- if let Some(parsed) = self.format.captures(&msg.content) {
- if let Some(op) = parsed.get(1) {
- let op_str = op.as_str().to_lowercase();
- if op_str != "release" && op_str != "repo" && op_str != "repository" {
- let response = MessageBuilder::new()
- .push("Invalid operation specified. Supported operations are `release,repo`")
- .build();
- if let Err(why) = msg.channel_id.say(&ctx.http, response) {
- println!("Failed to send gitea invalid option message {:?}", why);
- }
- }
- if let Some(full_url) = parsed.get(2) {
- let token = env::var("GITEA_TOKEN").expect("Expected a Gitea API token in GITEA_TOKEN environment variable");
- let mut core = Core::new().unwrap();
- //let https = HttpsConnector::new();
- let handler = core.handle();
- let client = Client::configure()
- .connector(HttpsConnector::new(4, &handler).unwrap())
- .build(&handler);
- let mut config = apis::configuration::Configuration::new(client);
- config.api_key = Some(apis::configuration::ApiKey {
- prefix: Some("token ".to_string()),
- key: token,
- });
- match Uri::from_str(full_url.as_str()) {
- Err(why) => {
- let response = MessageBuilder::new()
- .push(format!("Could not parse repository URL {:?}", why))
- .build();
- if let Err(why) = msg.channel_id.say(&ctx.http, response) {
- println!("Failed to send gitea error message {:?}", why);
- return;
- }
- }
- Ok(url) => {
- config.base_path = url.scheme().unwrap().to_owned() + "://" + url.host().unwrap() + "/api/v1";
- let client = apis::client::APIClient::new(config);
- if let Some(owner) = parsed.get(3) {
- if let Some(repo_name) = parsed.get(4) {
- if op_str == "release" {
- self.get_release(ctx, msg, full_url.as_str(), owner.as_str(), repo_name.as_str(), &client, &mut core);
- return;
- } else if op_str == "repo" || op_str == "repository" {
- self.get_repo(ctx, msg, full_url.as_str(), owner.as_str(), repo_name.as_str(), &client, &mut core);
- return;
- }
- }
- }
- }
- }
-
- }
-
- }
- }
- let response = MessageBuilder::new()
- .push(format!("Unknown error occurred"))
- .build();
- if let Err(why) = msg.channel_id.say(&ctx.http, response) {
- println!("Failed to send gitea unknown error message {:?}", why);
- return;
- }
- }
-
- fn valid(&self, _ctx: &Context, msg: &Message) -> bool {
- return self.format.is_match(&msg.content) && !msg.author.bot;
- }
-
- fn help(&self, ctx: &Context, msg:&Message) {
- let mut response = MessageBuilder::new();
- response.push("**Access the gitea API**\n!gitea release (repository URL)\n!gitea repo (repository URL)");
- if let Err(why) = msg.channel_id.say(&ctx.http, &response.build()) {
- println!("Failed to send gitea help message {:?}", why);
- }
- }
-
- fn valid_help(&self, _ctx: &Context, msg: &Message) -> bool {
- return self.help_format.is_match(&msg.content);
- }
- }
-
- impl CmdGitea {
- pub fn new() -> CmdGitea {
- return CmdGitea {
- format:
- RegexBuilder::new(r#"^!gitea\s+(release|repo|repository)\s+<?(https?://[^/\s]+/([^/\s]+)/([^/\s>]+))>?"#)
- .multi_line(true)
- .case_insensitive(true)
- .build()
- .unwrap(),
- help_format:
- RegexBuilder::new(r#"^!help\s*(?:gitea)"#)
- .case_insensitive(true)
- .build()
- .unwrap(),
- };
- }
-
- fn get_release<C>(&self, ctx: &Context, msg: &Message, full_url: &str, owner: &str, repo_name: &str, client: &apis::client::APIClient<C>, core: &mut Core) where C : hyper::client::Connect {
- let future = client.repository_api().repo_list_releases(owner, repo_name, 1, 5);
- //let result = async {future.await;};
- if let Err(async_err) = core.run(future.then(|result| {
- match result {
- Ok(items) => {
- // items is Vec of release
- if items.len() > 0 {
- //println!("Release info {:?}", items[0]);
- // releases found, use first one (most recent)
- if let Err(why) = msg.channel_id.send_message(&ctx.http, |m| {
- return m.embed(|e| {
- let mut files = "".to_owned();
- for f in items[0].assets().unwrap() {
- files += &format!("[{}]({})\n", f.name().unwrap(), f.browser_download_url().unwrap())
- }
- if files.len() > 4 {
- e.field("Download", files, true);
- }
- return e.colour(Colour::from_rgb(0, 200, 0))
- .title(format!("{} {}", repo_name, items[0].tag_name().unwrap()))
- .description(items[0].body().unwrap())
- .author(|a| {
- return a.name(items[0].name().unwrap())
- .url(full_url.to_owned() + "/releases");
- })
- .footer(|f| {
- return f.text(items[0].author().unwrap().login().unwrap())
- .icon_url(items[0].author().unwrap().avatar_url().unwrap());
- })
- });
- }) {
- println!("Failed to send gitea release message {:?}", why);
- return futures::future::ok::<u32, u32>(42);
- }
- } else {
- let response = MessageBuilder::new()
- .push(format!("No releases found for <{}>", full_url))
- .build();
- if let Err(why) = msg.channel_id.say(&ctx.http, response) {
- println!("Failed to send gitea error message {:?}", why);
- return futures::future::ok::<u32, u32>(42);
- }
- }
- return futures::future::ok::<u32, u32>(42);
- }
- Err(reason) => {
- println!("Gitea API request failed {:?}", reason);
- let response = MessageBuilder::new()
- .push(format!("Gitea API request failed {:?}", reason))
- .build();
- if let Err(why) = msg.channel_id.say(&ctx.http, response) {
- println!("Failed to send gitea error message {:?}", why);
- return futures::future::ok::<u32, u32>(42);
- }
- return futures::future::ok::<u32, u32>(42);
- }
- }
- })) {
- let response = MessageBuilder::new()
- .push(format!("Gitea API request failed to complete {:?}", async_err))
- .build();
- if let Err(why) = msg.channel_id.say(&ctx.http, response) {
- println!("Failed to send gitea error message {:?}", why);
- return;
- }
- return;
- }
- //return;
- }
-
- fn get_repo<C>(&self, ctx: &Context, msg: &Message, full_url: &str, owner: &str, repo_name: &str, client: &apis::client::APIClient<C>, core: &mut Core) where C : hyper::client::Connect {
- let future = client.repository_api().repo_get(owner, repo_name);
-
- match core.run(future) {
- Ok(repo) => {
- if let Err(why) = msg.channel_id.send_message(&ctx.http, |m| {
- //println!("{}", repo.clone_url().unwrap());
- if *repo.empty().unwrap() {
- return m.embed(|e| {
- return e.colour(Colour::from_rgb(200, 42, 42)) // ~dark red
- .title("")
- .description("-- Empty Repository --")
- .author(|a| {
- return a.icon_url(repo.avatar_url().unwrap())
- .name(repo.name().unwrap())
- .url(full_url);
- })
- .footer(|f| {
- let owner = repo.owner().unwrap();
- return f.text(owner.login().unwrap())
- .icon_url(owner.avatar_url().unwrap());
- });
- });
- }
- return m.embed(|e| {
- let mut desc = format!("{}", repo.description().unwrap());
- if let Some(website) = repo.website() {
- if website == "" {
- desc = format!("{desc}\n[Releases]({html}/releases)", desc=desc, html=repo.html_url().unwrap());
- } else {
- desc = format!("{desc}\n[Website]({url})\n[Releases]({html}/releases)", desc=desc, url=website, html=repo.html_url().unwrap());
- }
- }
- //desc = format!("{}\nCreated at {} (updated at {})", desc, repo.created_at().unwrap(), repo.updated_at().unwrap());
- return e.colour(Colour::from_rgb(128, 42, 42)) // ~brown
- .title("")
- .description(desc)
- .author(|a| {
- return a.icon_url(repo.avatar_url().unwrap())
- .name(format!("{}", repo.name().unwrap()))
- .url(full_url);
- })
- .footer(|f| {
- let owner = repo.owner().unwrap();
- return f.text(owner.login().unwrap())
- .icon_url(owner.avatar_url().unwrap());
- })
- .field("Watchers", format!("{} ({}**\\***)", repo.watchers_count().unwrap(), repo.stars_count().unwrap()), true)
- .field("Issues", format!("{}", repo.open_issues_count().unwrap()), true)
- .field("Forks", format!("{} ({} PRs)", repo.forks_count().unwrap(), repo.open_pr_counter().unwrap()), true)
- .field("Size", format!("{} KB", repo.size().unwrap()), true)
- //.field("Releases", format!("{}", repo.release_counter().unwrap()), true) // always zero (why?)
- .field("Created At", format!("{}", repo.created_at().unwrap()), true);
- });
- }) {
- println!("Failed to send gitea release message {:?}", why);
- }
- }
- Err(async_err) => {
- let response = MessageBuilder::new()
- .push(format!("Gitea API request failed to complete {:?}", async_err))
- .build();
- if let Err(why) = msg.channel_id.say(&ctx.http, response) {
- println!("Failed to send gitea error message {:?}", why);
- }
- }
- }
- }
- }
|