text:
use crate::error::{Result, VitaError};
use crate::{DataSource, IntoSubdomain};
use async_trait::async_trait;
use dotenv::dotenv;
use reqwest::Client;
use serde::Deserialize;
use std::env;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{info, trace, warn};

struct Creds {
    key: String,
}

impl Creds {
    pub fn read_creds() -> Result<Self> {
        dotenv().ok();
        match env::var("C99_KEY") {
            Ok(key) => Ok(Self { key }),
            Err(_) => Err(VitaError::UnsetKeys(vec!["C99_KEY".into()])),
        }
    }
}

#[derive(Debug, Deserialize)]
struct C99Result {
    subdomains: Option<Vec<C99Item>>,
}

#[derive(Debug, Deserialize)]
struct C99Item {
    subdomain: String,
}

impl IntoSubdomain for C99Result {
    fn subdomains(&self) -> Vec<String> {
        self.subdomains
            .iter()
            .flatten()
            .map(|s| s.subdomain.to_string())
            .collect()
    }
}

#[derive(Default, Clone)]
pub struct C99 {
    client: Client,
}

impl C99 {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    fn build_url(&self, host: &str, api_key: &str) -> String {
        format!(
            "https://api.c99.nl/subdomainfinder?key={}&domain={}&json",
            api_key, host
        )
    }
}

#[async_trait]
impl DataSource for C99 {
    async fn run(&self, host: Arc<String>, mut tx: Sender<Vec<String>>) -> Result<()> {
        trace!("fetching data from C99 for: {}", &host);
        let api_key = match Creds::read_creds() {
            Ok(creds) => creds.key,
            Err(e) => return Err(e),
        };

        let uri = self.build_url(&host, &api_key);
        let resp = self.client.get(&uri).send().await?;

        if resp.status().is_success() {
            let resp: C99Result = resp.json().await?;
            let subdomains = resp.subdomains();
            if !subdomains.is_empty() {
                info!("Discovered {} results for {}", &subdomains.len(), &host);
                let _ = tx.send(subdomains).await;
                return Ok(());
            }
        }

        warn!("no results for {} from C99", &host);
        Err(VitaError::SourceError("C99".into()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use matches::matches;
    use tokio::sync::mpsc::channel;

    #[ignore]
    #[tokio::test]
    async fn returns_results() {
        let (tx, mut rx) = channel(1);
        let host = Arc::new("hackerone.com".to_owned());
        let _ = C99::default().run(host, tx).await;
        let mut results = Vec::new();
        for r in rx.recv().await {
            results.extend(r)
        }
        assert!(!results.is_empty());
    }

    #[ignore]
    #[tokio::test]
    async fn handle_no_results() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            C99::default().run(host, tx).await.err().unwrap(),
            VitaError::SourceError(_)
        ));
    }
}


text:
use crate::error::{Result, VitaError};
use crate::{DataSource, IntoSubdomain};
use async_trait::async_trait;
use reqwest::Client;
use serde::Deserialize;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{info, trace, warn};

#[derive(Deserialize, Debug)]
struct Subdomain {
    hostname: String,
}

#[derive(Deserialize, Debug)]
struct AlienvaultResult {
    passive_dns: Vec<Subdomain>,
    count: i32,
}

impl IntoSubdomain for AlienvaultResult {
    fn subdomains(&self) -> Vec<String> {
        self.passive_dns
            .iter()
            .map(|s| s.hostname.to_owned())
            .collect()
    }
}

#[derive(Default, Clone)]
pub struct AlienVault {
    client: Client,
}

impl AlienVault {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    fn build_url(&self, host: &str) -> String {
        format!(
            "https://otx.alienvault.com/api/v1/indicators/domain/{}/passive_dns",
            host
        )
    }
}

#[async_trait]
impl DataSource for AlienVault {
    async fn run(&self, host: Arc<String>, mut tx: Sender<Vec<String>>) -> Result<()> {
        trace!("fetching data from alienvault for: {}", &host);
        let uri = self.build_url(&host);
        let resp: AlienvaultResult = self.client.get(&uri).send().await?.json().await?;

        if resp.count != 0 {
            let subdomains = resp.subdomains();
            info!("Discovered {} results for {}", &subdomains.len(), &host);
            let _ = tx.send(subdomains).await;
            return Ok(());
        }

        warn!("No results for {} from AlienVault", &host);
        Err(VitaError::SourceError("AlienVault".into()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use matches::matches;
    use tokio::sync::mpsc::channel;

    #[test]
    fn url_builder() {
        let correct_uri = "https://otx.alienvault.com/api/v1/indicators/domain/\
        hackerone.com/passive_dns";

        assert_eq!(
            correct_uri,
            AlienVault::default().build_url("hackerone.com")
        );
    }

    // Checks to see if the run function returns subdomains
    #[tokio::test]
    async fn returns_results() {
        let (tx, mut rx) = channel(1);
        let host = Arc::new("hackerone.com".to_string());
        let _ = AlienVault::default().run(host, tx).await.unwrap();
        let mut results = Vec::new();
        for r in rx.recv().await {
            results.extend(r)
        }

        assert!(!results.is_empty());
    }

    #[tokio::test]
    async fn handle_no_results() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            AlienVault::default().run(host, tx).await.err().unwrap(),
            VitaError::SourceError(_)
        ))
    }
}

repo_name: junnlikestea/vita

repo_language: Rust

mime_type: text/plain


text:
use crate::error::{Result, VitaError};
use crate::{DataSource, IntoSubdomain};
use async_trait::async_trait;
use reqwest::Client;
use serde_json::value::Value;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{info, trace, warn};
use url::Url;

struct WaybackResult {
    data: Value,
}

impl WaybackResult {
    fn new(data: Value) -> Self {
        Self { data }
    }
}

//TODO: this could be cleaned up, to avoid creating the extra vec `vecs`
impl IntoSubdomain for WaybackResult {
    fn subdomains(&self) -> Vec<String> {
        let arr = self.data.as_array().unwrap();
        let vecs: Vec<&str> = arr.iter().map(|s| s[0].as_str().unwrap()).collect();
        vecs.into_iter()
            .filter_map(|a| {
                Url::parse(a)
                    .ok()
                    .and_then(|u| u.host_str().map(|h| h.into()))
            })
            .collect()
    }
}

#[derive(Default, Clone)]
pub struct Wayback {
    client: Client,
}

impl Wayback {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    fn build_url(&self, host: &str) -> String {
        format!(
            "https://web.archive.org/cdx/search/cdx?url=*.{}/*&output=json\
    &fl=original&collapse=urlkey&limit=100000",
            host
        )
    }
}

#[async_trait]
impl DataSource for Wayback {
    async fn run(&self, host: Arc<String>, mut tx: Sender<Vec<String>>) -> Result<()> {
        trace!("fetching data from wayback for: {}", &host);
        let uri = self.build_url(&host);
        let resp: Option<Value> = self.client.get(&uri).send().await?.json().await?;

        if let Some(data) = resp {
            let subdomains = WaybackResult::new(data).subdomains();
            if !subdomains.is_empty() {
                info!("Discovered {} results for: {}", &subdomains.len(), &host);
                let _ = tx.send(subdomains).await;
                return Ok(());
            }
        }

        warn!("no results found for {} from Wayback Machine", &host);
        Err(VitaError::SourceError("Wayback Machine".into()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use matches::matches;
    use tokio::sync::mpsc::channel;

    #[test]
    fn url_builder() {
        let correct_uri =
            "https://web.archive.org/cdx/search/cdx?url=*.hackerone.com/*&output=json\
    &fl=original&collapse=urlkey&limit=100000";
        assert_eq!(correct_uri, Wayback::default().build_url("hackerone.com"));
    }

    #[ignore] // hangs forever on windows for some reasons?
    #[tokio::test]
    async fn returns_results() {
        let (tx, mut rx) = channel(20);
        let host = Arc::new("hackerone.com".to_owned());
        let _ = Wayback::default().run(host, tx).await;
        let mut results = Vec::new();
        for r in rx.recv().await {
            results.extend(r)
        }
        assert!(!results.is_empty());
    }

    #[ignore]
    #[tokio::test]
    async fn handle_no_results() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            Wayback::default().run(host, tx).await.err().unwrap(),
            VitaError::SourceError(_)
        ));
    }
}


text:
use crate::error::{Result, VitaError};
use crate::{DataSource, IntoSubdomain};
use async_trait::async_trait;
use reqwest::Client;
use serde::Deserialize;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{info, trace, warn};

#[derive(Deserialize)]
struct Subdomain {
    id: String,
}

#[derive(Deserialize)]
struct VirustotalResult {
    data: Option<Vec<Subdomain>>,
}

impl IntoSubdomain for VirustotalResult {
    fn subdomains(&self) -> Vec<String> {
        self.data
            .iter()
            .flatten()
            .map(|s| s.id.to_owned())
            .collect()
    }
}

#[derive(Default, Clone)]
pub struct VirusTotal {
    client: Client,
}

impl VirusTotal {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    fn build_url(&self, host: &str) -> String {
        // TODO: can we gather the subdomains using:
        // Handle pagenation
        // https://www.virustotal.com/vtapi/v2/domain/report
        format!(
            "https://www.virustotal.com/ui/domains/{}/subdomains?limit=40",
            host
        )
    }
}

#[async_trait]
impl DataSource for VirusTotal {
    async fn run(&self, host: Arc<String>, mut tx: Sender<Vec<String>>) -> Result<()> {
        trace!("fetching data from virustotal for: {}", &host);
        let uri = self.build_url(&host);
        let resp: VirustotalResult = self.client.get(&uri).send().await?.json().await?;

        let subdomains = resp.subdomains();
        if !subdomains.is_empty() {
            info!("Discovered {} results for {}", &subdomains.len(), &host);
            let _ = tx.send(subdomains).await;
            return Ok(());
        }

        warn!("no results found for {} from VirusTotal", &host);
        Err(VitaError::SourceError("VirusTotal".into()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use matches::matches;
    use tokio::sync::mpsc::channel;

    // IGNORE by default since we have limited api calls.
    #[tokio::test]
    #[ignore]
    async fn returns_results() {
        let (tx, mut rx) = channel(1);
        let host = Arc::new("hackerone.com".to_owned());
        let _ = VirusTotal::default().run(host, tx).await;
        let mut results = Vec::new();
        for r in rx.recv().await {
            results.extend(r)
        }
        assert!(!results.is_empty());
    }

    #[ignore]
    #[tokio::test]
    async fn handle_no_results() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            VirusTotal::default().run(host, tx).await.err().unwrap(),
            VitaError::SourceError(_)
        ));
    }
}


text:
use crate::error::{Result, VitaError};
use crate::{DataSource, IntoSubdomain};
use async_trait::async_trait;
use dotenv::dotenv;
use reqwest::Client;
use serde::Deserialize;
use std::env;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{info, warn};

#[derive(Debug, PartialEq)]
struct Creds {
    app_id: String,
    app_secret: String,
}

impl Creds {
    pub fn read_creds() -> Result<Self> {
        dotenv().ok();
        let app_id = env::var("FB_APP_ID");
        let app_secret = env::var("FB_APP_SECRET");

        match (app_id, app_secret) {
            (Ok(id), Ok(secret)) => Ok(Self {
                app_id: id,
                app_secret: secret,
            }),
            _ => Err(VitaError::UnsetKeys(vec![
                "FB_APP_ID".into(),
                "FB_APP_SECRET".into(),
            ])),
        }
    }

    pub async fn authenticate(&self, client: Client) -> Result<String> {
        // created a struct because deserializing into a serde_json::Value
        // was returning the access token with quotation marks"tokeninhere"
        // but wasn't doing that as a struct.
        #[derive(Deserialize)]
        struct AuthResp {
            access_token: String,
        }

        let auth_url = format!(
            "https://graph.facebook.com/oauth/access_token?client_id={}\
            &client_secret={}&grant_type=client_credentials",
            self.app_id, self.app_secret
        );

        let resp: Option<AuthResp> = client.get(&auth_url).send().await?.json().await?;

        if let Some(r) = resp {
            Ok(r.access_token)
        } else {
            Err(VitaError::AuthError("Facebook".into()))
        }
    }
}

#[derive(Deserialize, Debug)]
struct Subdomains {
    domains: Vec<String>,
}

#[derive(Deserialize, Debug)]
struct FacebookResult {
    data: Vec<Subdomains>,
}

impl IntoSubdomain for FacebookResult {
    fn subdomains(&self) -> Vec<String> {
        self.data
            .iter()
            .flat_map(|s| s.domains.to_owned())
            .collect()
    }
}

//TODO: creds should probably be provided on Facebook::new
#[derive(Default, Clone)]
pub struct Facebook {
    client: Client,
}

impl Facebook {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    fn build_url(&self, host: &str, token: &str) -> String {
        format!(
            "https://graph.facebook.com/certificates?fields=domains&access_token={}&query=*.{}",
            token, host
        )
    }
}

#[async_trait]
impl DataSource for Facebook {
    async fn run(&self, host: Arc<String>, mut tx: Sender<Vec<String>>) -> Result<()> {
        let access_token = match Creds::read_creds() {
            Ok(c) => c.authenticate(self.client.clone()).await?,
            Err(e) => return Err(e),
        };

        let uri = self.build_url(&host, &access_token);
        let resp: Option<FacebookResult> = self.client.get(&uri).send().await?.json().await?;

        if let Some(data) = resp {
            let subdomains = data.subdomains();
            if !subdomains.is_empty() {
                info!("Discovered {} results for {}", &subdomains.len(), &host);
                let _ = tx.send(subdomains).await;
                return Ok(());
            }
        }

        warn!("got no results for {} from Facebook", host);
        Err(VitaError::SourceError("Facebook".into()))
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    use crate::client;
    use matches::matches;
    use tokio::sync::mpsc::channel;

    // checks if we can fetch the credentials from an .env file.
    #[ignore]
    #[test]
    fn get_creds() {
        dotenv().ok();
        let app_id = env::var("FB_APP_ID").unwrap();
        let app_secret = env::var("FB_APP_SECRET").unwrap();
        let creds: Creds = Creds { app_id, app_secret };
        assert_eq!(creds, Creds::read_creds().unwrap());
    }

    // ignoring passed locally
    #[ignore]
    #[test]
    fn get_no_creds() {
        assert!(matches!(
            Creds::read_creds().err().unwrap(),
            VitaError::UnsetKeys(_)
        ));
    }

    // Checks if we can authenticate with Facebook.
    #[ignore]
    #[tokio::test]
    async fn auth() {
        let client = client!();
        let token = Creds::read_creds()
            .unwrap()
            .authenticate(client)
            .await
            .unwrap();
        assert!(token.len() > 1);
    }

    // Checks to see if the run function returns subdomains
    #[ignore]
    #[tokio::test]
    async fn returns_results() {
        let (tx, mut rx) = channel(1);
        let host = Arc::new("hackerone.com".to_owned());
        let _ = Facebook::default().run(host, tx).await;
        let mut results = Vec::new();
        for r in rx.recv().await {
            results.extend(r)
        }
        assert!(!results.is_empty());
    }

    // Checks that if we get no results that we just return an error.
    // test is ignored by default to preserve limits
    #[ignore]
    #[tokio::test]
    async fn handle_no_results() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            Facebook::default().run(host, tx).await.err().unwrap(),
            VitaError::SourceError(_)
        ));
    }
}


text:
use crate::error::{Result, VitaError};
use crate::{DataSource, IntoSubdomain};
use async_trait::async_trait;
use reqwest::Client;
use serde::Deserialize;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{info, trace, warn};

#[derive(Deserialize, Hash, PartialEq, Debug, Eq)]
struct CrtshResult {
    name_value: String,
}

impl IntoSubdomain for Vec<CrtshResult> {
    fn subdomains(&self) -> Vec<String> {
        self.iter().map(|s| s.name_value.to_owned()).collect()
    }
}

#[derive(Default, Clone)]
pub struct Crtsh {
    client: Client,
}

impl Crtsh {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    fn build_url(&self, host: &str) -> String {
        format!("https://crt.sh/?q=%.{}&output=json", host)
    }
}

#[async_trait]
impl DataSource for Crtsh {
    async fn run(&self, host: Arc<String>, mut tx: Sender<Vec<String>>) -> Result<()> {
        trace!("fetching data from crt.sh for: {}", &host);
        let uri = self.build_url(&host);
        let resp: Option<Vec<CrtshResult>> = self.client.get(&uri).send().await?.json().await?;

        if let Some(data) = resp {
            let subdomains = data.subdomains();
            if !subdomains.is_empty() {
                info!("Discovered {} results for: {}", subdomains.len(), &host);
                let _ = tx.send(subdomains).await;
                return Ok(());
            }
        }

        warn!("no results for {} from Crt.sh", &host);
        Err(VitaError::SourceError("Crt.sh".into()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use matches::matches;
    use tokio::sync::mpsc::channel;

    #[test]
    fn url_builder() {
        let correct_uri = "https://crt.sh/?q=%.hackerone.com&output=json";
        assert_eq!(correct_uri, Crtsh::default().build_url("hackerone.com"));
    }

    #[ignore]
    #[tokio::test]
    async fn returns_results() {
        let (tx, mut rx) = channel(1);
        let host = Arc::new("hackerone.com".to_owned());
        let _ = Crtsh::default().run(host, tx).await;
        let mut results = Vec::new();
        for r in rx.recv().await {
            results.extend(r)
        }
        assert!(!results.is_empty());
    }

    #[ignore] // tests passing locally but failing on linux ci?
    #[tokio::test]
    async fn handle_no_results() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            Crtsh::default().run(host, tx).await.err().unwrap(),
            VitaError::SourceError(_)
        ));
    }
}


text:
use crate::error::{Result, VitaError};
use crate::{DataSource, IntoSubdomain};
use async_trait::async_trait;
use reqwest::Client;
use serde_json::value::Value;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{info, trace, warn};

struct SublisterResult {
    items: Vec<Value>,
}

impl SublisterResult {
    fn new(items: Vec<Value>) -> Self {
        SublisterResult { items }
    }
}

//TODO: can this just be collected without the map?
impl IntoSubdomain for SublisterResult {
    fn subdomains(&self) -> Vec<String> {
        self.items
            .iter()
            .map(|s| s.as_str().unwrap().to_owned())
            .collect()
    }
}

#[derive(Default, Clone)]
pub struct Sublister {
    client: Client,
}

impl Sublister {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    fn build_url(&self, host: &str) -> String {
        format!("https://api.sublist3r.com/search.php?domain={}", host)
    }
}

#[async_trait]
impl DataSource for Sublister {
    async fn run(&self, host: Arc<String>, mut tx: Sender<Vec<String>>) -> Result<()> {
        trace!("fetching data from sublister for: {}", &host);
        let uri = self.build_url(&host);
        let resp: Option<Value> = self.client.get(&uri).send().await?.json().await?;

        if let Some(data) = resp {
            let subdomains = SublisterResult::new(data.as_array().unwrap().to_owned()).subdomains();
            if !subdomains.is_empty() {
                info!("Discovered {} results for {}", &subdomains.len(), &host);
                let _ = tx.send(subdomains).await;
                return Ok(());
            }
        }

        warn!("no results for {} from Sublist3r", &host);
        Err(VitaError::SourceError("Sublist3r".into()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use matches::matches;
    use tokio::sync::mpsc::channel;

    #[test]
    fn url_builder() {
        let correct_uri = "https://api.sublist3r.com/search.php?domain=hackerone.com";
        assert_eq!(correct_uri, Sublister::default().build_url("hackerone.com"));
    }

    //TODO: tweak test for GithubActions (passed locally)
    #[tokio::test]
    #[ignore]
    async fn returns_results() {
        let (tx, mut rx) = channel(1);
        let host = Arc::new("hackerone.com".to_owned());
        let _ = Sublister::default().run(host, tx).await;
        let mut results = Vec::new();
        for r in rx.recv().await {
            results.extend(r)
        }
        assert!(!results.is_empty());
    }

    #[tokio::test]
    async fn handle_no_results() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            Sublister::default().run(host, tx).await.err().unwrap(),
            VitaError::SourceError(_)
        ));
    }
}


text:
use crate::error::{Result, VitaError};
use crate::{DataSource, IntoSubdomain};
use async_trait::async_trait;
use dotenv::dotenv;
use reqwest::header::AUTHORIZATION;
use reqwest::Client;
use serde::Deserialize;
use std::env;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{info, trace, warn};

struct Creds {
    key: String,
}

impl Creds {
    pub fn read_creds() -> Result<Self> {
        dotenv().ok();
        match env::var("CHAOS_KEY") {
            Ok(key) => Ok(Self { key }),
            Err(_) => Err(VitaError::UnsetKeys(vec!["CHAOS_KEY".into()])),
        }
    }
}

#[derive(Deserialize, Debug)]
struct ChaosResult {
    domain: String,
    subdomains: Vec<String>,
}

impl IntoSubdomain for ChaosResult {
    fn subdomains(&self) -> Vec<String> {
        self.subdomains
            .iter()
            .map(|s| format!("{}.{}", s, self.domain))
            .collect()
    }
}

#[derive(Default, Clone)]
pub struct Chaos {
    client: Client,
}

impl Chaos {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    fn build_url(&self, host: &str) -> String {
        format!("https://dns.projectdiscovery.io/dns/{}/subdomains", host)
    }
}

#[async_trait]
impl DataSource for Chaos {
    async fn run(&self, host: Arc<String>, mut tx: Sender<Vec<String>>) -> Result<()> {
        trace!("fetching data from projectdiscovery choas for: {}", &host);
        let api_key = match Creds::read_creds() {
            Ok(creds) => creds.key,
            Err(e) => return Err(e),
        };
        let uri = self.build_url(&host);
        let resp = self
            .client
            .get(&uri)
            .header(AUTHORIZATION, api_key)
            .send()
            .await?;

        if resp.status().is_client_error() {
            warn!("got status: {} from chaos", resp.status().as_str());
            return Err(VitaError::AuthError("Chaos".into()));
        } else {
            let resp: ChaosResult = resp.json().await?;
            let subdomains = resp.subdomains();
            if !subdomains.is_empty() {
                info!("Discovered {} results for: {}", &subdomains.len(), &host);
                let _ = tx.send(subdomains).await;
                return Ok(());
            }
        }

        warn!("no results for {} from Chaos", &host);
        Err(VitaError::SourceError("Chaos".into()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use matches::matches;
    use tokio::sync::mpsc::channel;

    // Ignore, passed locally.
    #[ignore]
    #[tokio::test]
    async fn returns_results() {
        let (tx, mut rx) = channel(1);
        let host = Arc::new("hackerone.com".to_owned());
        let _ = Chaos::default().run(host, tx).await;
        let mut results = Vec::new();
        for r in rx.recv().await {
            results.extend(r)
        }
        assert!(!results.is_empty());
    }

    // Ignore, passed locally.
    #[tokio::test]
    #[ignore]
    async fn handle_no_results() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            Chaos::default().run(host, tx).await.err().unwrap(),
            VitaError::SourceError(_)
        ));
    }
}


text:
use crate::error::{Result, VitaError};
use crate::{DataSource, IntoSubdomain};
use async_trait::async_trait;
use reqwest::Client;
use serde::Deserialize;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{info, trace, warn};

#[derive(Deserialize)]
struct ThreatminerResult {
    results: Vec<String>,
}

impl IntoSubdomain for ThreatminerResult {
    //todo: does it have to be HashSet<String> or can we change to HashSet<&str>
    fn subdomains(&self) -> Vec<String> {
        self.results.iter().map(|s| s.to_owned()).collect()
    }
}

#[derive(Default, Clone)]
pub struct ThreatMiner {
    client: Client,
}

impl ThreatMiner {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    fn build_url(&self, host: &str) -> String {
        format!(
            "https://api.threatminer.org/v2/domain.php?q={}&api=True&rt=5",
            host
        )
    }
}

#[async_trait]
impl DataSource for ThreatMiner {
    async fn run(&self, host: Arc<String>, mut tx: Sender<Vec<String>>) -> Result<()> {
        trace!("fetching data from threatminer for: {}", &host);
        let uri = self.build_url(&host);
        let resp: Option<ThreatminerResult> = self.client.get(&uri).send().await?.json().await?;

        if let Some(data) = resp {
            let subdomains = data.subdomains();
            if !subdomains.is_empty() {
                info!("Discovered {} results for: {}", &subdomains.len(), &host);
                let _ = tx.send(subdomains).await;
                return Ok(());
            }
        }

        warn!("no results found for {} from ThreatMiner", &host);
        Err(VitaError::SourceError("ThreatMiner".into()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use matches::matches;
    use tokio::sync::mpsc::channel;

    #[test]
    fn url_builder() {
        let correct_uri = "https://api.threatminer.org/v2/domain.php?q=hackerone.com&api=True&rt=5";
        assert_eq!(
            correct_uri,
            ThreatMiner::default().build_url("hackerone.com")
        );
    }

    // Checks to see if the run function returns subdomains
    #[tokio::test]
    async fn returns_results() {
        let (tx, mut rx) = channel(1);
        let host = Arc::new("hackerone.com".to_owned());
        let _ = ThreatMiner::default().run(host, tx).await;
        let mut results = Vec::new();
        for r in rx.recv().await {
            results.extend(r)
        }
        assert!(!results.is_empty());
    }

    //Some("WaybackMachine couldn't find results for: anVubmxpa2VzdGVh.com")
    #[tokio::test]
    async fn handle_no_results() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            ThreatMiner::default().run(host, tx).await.err().unwrap(),
            VitaError::SourceError(_)
        ));
    }
}


text:
use crate::error::{Result, VitaError};
use crate::{DataSource, IntoSubdomain};
use async_trait::async_trait;
use dotenv::dotenv;
use reqwest::header::ACCEPT;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::env;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{info, trace, warn};

struct Creds {
    key: String,
    secret: String,
}

impl Creds {
    fn from_env() -> Result<Self> {
        dotenv().ok();
        let key = env::var("PASSIVETOTAL_KEY");
        let secret = env::var("PASSIVETOTAL_SECRET");
        match (key, secret) {
            (Ok(k), Ok(s)) => Ok(Self { key: k, secret: s }),
            _ => Err(VitaError::UnsetKeys(vec![
                "PASSIVETOTAL_KEY".into(),
                "PASSIVETOTAL_SECRET".into(),
            ])),
        }
    }
}

#[derive(Serialize)]
struct Query {
    query: String,
}

impl Query {
    fn new(host: &str) -> Self {
        Self {
            query: host.to_string(),
        }
    }
}

#[derive(Debug, Deserialize)]
struct PassiveTotalResult {
    success: bool,
    #[serde(rename = "primaryDomain")]
    primary_domain: String,
    subdomains: Vec<String>,
}

impl IntoSubdomain for PassiveTotalResult {
    fn subdomains(&self) -> Vec<String> {
        self.subdomains
            .iter()
            .map(|s| format!("{}.{}", s, self.primary_domain))
            .collect()
    }
}

#[derive(Default, Clone)]
pub struct PassiveTotal {
    client: Client,
}

impl PassiveTotal {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    fn build_url(&self) -> String {
        "https://api.passivetotal.org/v2/enrichment/subdomains".to_string()
    }
}

#[async_trait]
impl DataSource for PassiveTotal {
    async fn run(&self, host: Arc<String>, mut tx: Sender<Vec<String>>) -> Result<()> {
        trace!("fetching data from passivetotal for: {}", &host);
        let creds = match Creds::from_env() {
            Ok(c) => c,
            Err(e) => return Err(e),
        };

        let uri = self.build_url();
        let query = Query::new(&host);
        let resp = self
            .client
            .get(&uri)
            .basic_auth(&creds.key, Some(&creds.secret))
            .header(ACCEPT, "application/json")
            .json(&query)
            .send()
            .await?;

        if resp.status().is_client_error() {
            warn!("got status: {} from passivetotal", resp.status().as_str());
            return Err(VitaError::AuthError("Passivetotal".into()));
        } else {
            let resp: PassiveTotalResult = resp.json().await?;
            let subdomains = resp.subdomains();

            if !subdomains.is_empty() {
                info!("Discovered {} results for: {}", &subdomains.len(), &host);
                let _ = tx.send(subdomains).await;
                return Ok(());
            }
        }

        warn!("no results for {} from PassiveTotal", &host);
        Err(VitaError::SourceError("PassiveTotal".into()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use matches::matches;
    use tokio::sync::mpsc::channel;

    // Checks to see if the run function returns subdomains
    #[tokio::test]
    #[ignore]
    async fn returns_results() {
        let (tx, mut rx) = channel(1);
        let host = Arc::new("hackerone.com".to_owned());
        let _ = PassiveTotal::default().run(host, tx).await;
        let mut results = Vec::new();
        for r in rx.recv().await {
            results.extend(r)
        }
        assert!(!results.is_empty());
    }

    #[tokio::test]
    #[ignore]
    async fn handle_no_results() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            PassiveTotal::default().run(host, tx).await.err().unwrap(),
            VitaError::SourceError(_)
        ));
    }
}


text:
use crate::error::Result;
use crate::error::VitaError;
use crate::{DataSource, IntoSubdomain};
use async_trait::async_trait;
use dotenv::dotenv;
use reqwest::Client;
use serde::Deserialize;
use std::env;
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{info, trace, warn};

struct Creds {
    token: String,
}

impl Creds {
    pub fn read_creds() -> Result<Self> {
        dotenv().ok();
        match env::var("BINARYEDGE_TOKEN") {
            Ok(token) => Ok(Self { token }),
            Err(_) => Err(VitaError::UnsetKeys(vec!["BINARYEDGE_TOKEN".into()])),
        }
    }
}

#[derive(Deserialize)]
struct BinaryEdgeResponse {
    page: i32,
    pagesize: i32,
    total: i32,
    events: Vec<String>,
}

impl IntoSubdomain for BinaryEdgeResponse {
    fn subdomains(&self) -> Vec<String> {
        self.events.iter().map(|s| s.to_owned()).collect()
    }
}

#[derive(Default, Clone)]
pub struct BinaryEdge {
    client: Client,
}

impl BinaryEdge {
    pub fn new(client: Client) -> Self {
        Self { client }
    }

    fn build_url(&self, host: &str, page: Option<i32>) -> String {
        match page {
            Some(p) => format!(
                "https://api.binaryedge.io/v2/query/domains/subdomain/{}?page={}",
                host, p
            ),
            None => format!(
                "https://api.binaryedge.io/v2/query/domains/subdomain/{}",
                host
            ),
        }
    }
}

//TODO: Clean this up, make pages fetch async
// fetches the page in sequential order, it would be better to fetch them concurrently,
// but for the small amount of pages it probably doesn't matter
#[async_trait]
impl DataSource for BinaryEdge {
    async fn run(&self, host: Arc<String>, mut tx: Sender<Vec<String>>) -> Result<()> {
        trace!("fetching data from binaryedge for: {}", &host);
        let mut tasks = Vec::new();
        let mut results = Vec::new();
        let resp = next_page(self.client.clone(), host.clone(), None).await?;

        // insert subdomains from first page.
        results.extend(resp.subdomains().into_iter());
        let mut page = resp.page;

        loop {
            let host = host.clone();
            let client = self.client.clone();

            if page > 0 && page * resp.pagesize >= resp.total {
                break;
            }

            page += 1;
            tasks.push(tokio::task::spawn(async move {
                next_page(client, host, Some(page)).await
            }));
        }

        for t in tasks {
            let subs = t.await??.subdomains().into_iter();
            results.extend(subs);
        }

        info!("Discovered {} results for: {}", results.len(), &host);
        if !results.is_empty() {
            let _ = tx.send(results).await;
            return Ok(());
        }

        warn!("no results for {} from BinaryEdge", &host);
        Err(VitaError::SourceError("BinaryEdge".into()))
    }
}

async fn next_page(
    client: Client,
    host: Arc<String>,
    page: Option<i32>,
) -> Result<BinaryEdgeResponse> {
    trace!("fetching a page from binaryedge for: {}", &host);
    let uri = BinaryEdge::default().build_url(&host, page);
    let token = match Creds::read_creds() {
        Ok(creds) => creds.token,
        Err(e) => return Err(e),
    };

    let resp = client.get(&uri).header("X-Key", token).send().await?;

    if resp.status().is_success() {
        let be: BinaryEdgeResponse = resp.json().await?;
        return Ok(be);
    }

    info!("binaryedge returned authentication error");
    Err(VitaError::AuthError("BinaryEdge".into()))
}

#[cfg(test)]
mod tests {
    use super::*;
    use matches::matches;
    use tokio::sync::mpsc::channel;

    // Tests passed locally, ignoring for now.
    #[tokio::test]
    #[ignore]
    async fn returns_results() {
        let (tx, mut rx) = channel(1);
        let host = Arc::new("hackerone.com".to_string());
        let _ = BinaryEdge::default().run(host, tx).await;
        let mut results = Vec::new();
        for r in rx.recv().await {
            results.extend(r)
        }
        assert!(!results.is_empty());
    }

    #[tokio::test]
    #[ignore]
    async fn handle_no_results() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            BinaryEdge::default().run(host, tx).await.err().unwrap(),
            VitaError::SourceError(_)
        ))
    }

    #[tokio::test]
    #[ignore]
    async fn handle_auth_error() {
        let (tx, _rx) = channel(1);
        let host = Arc::new("anVubmxpa2VzdGVh.com".to_string());
        assert!(matches!(
            BinaryEdge::default().run(host, tx).await.err().unwrap(),
            VitaError::AuthError(_)
        ));
    }
}


text:
extern crate vita;
use clap::{App, Arg};
use futures::stream::StreamExt;
use std::collections::HashSet;
use std::env;
use std::fs::File;
use std::io::{self, BufRead, BufReader};
use vita::error::Result;
use vita::{CleanExt, PostProcessor, Runner};

#[tokio::main]
async fn main() -> Result<()> {
    let ParsedArgs {
        runner,
        cleaner,
        flush,
        hosts,
    } = ParsedArgs::new(create_clap_app())?;
    let mut results: HashSet<String> = HashSet::new();

    let mut stream = runner.run(hosts).await?;
    while let Some(v) = stream.next().await {
        v.iter().clean(&cleaner).for_each(|r| {
            if flush {
                println!("{}", r);
            } else {
                results.insert(r);
            }
        });
    }

    if !flush {
        results.iter().for_each(|r| println!("{}", r));
    }

    Ok(())
}

struct ParsedArgs {
    runner: Runner,
    cleaner: PostProcessor,
    flush: bool,
    hosts: HashSet<String>,
}

impl ParsedArgs {
    fn new(app: clap::App<'static, 'static>) -> Result<Self> {
        let matches = app.get_matches();
        // make it a hashset incase user provided duplicate domains
        let mut hosts: HashSet<String> = HashSet::new();
        let mut excluded: Vec<&str> = Vec::new();
        let max_concurrent: usize = matches.value_of("concurrency").unwrap().parse()?;
        let timeout: u64 = matches.value_of("timeout").unwrap().parse()?;

        if matches.is_present("verbosity") {
            let builder = tracing_subscriber::fmt()
                .with_env_filter(matches.value_of("verbosity").unwrap())
                .with_filter_reloading();
            let _handle = builder.reload_handle();
            builder.try_init()?;
        }

        if matches.is_present("file") {
            let input = matches.value_of("input").unwrap();
            hosts = read_input(Some(input))?;
        } else if matches.is_present("domain") {
            hosts.insert(matches.value_of("input").unwrap().to_string());
        } else {
            hosts = read_input(None)?;
        }

        if matches.is_present("exclude") {
            excluded = matches.values_of("exclude").unwrap().collect();
        }

        let mut cleaner = PostProcessor::default();
        if matches.is_present("subs-only") {
            cleaner.any_subdomain(hosts.clone());
        } else {
            cleaner.any_root(hosts.clone());
        }

        let mut runner = Runner::default()
            .concurrency(max_concurrent)
            .timeout(timeout)
            .free_sources()
            .exclude(&excluded);
        if matches.is_present("all_sources") {
            runner = runner.all_sources().exclude(&excluded);
        }

        Ok(Self {
            runner,
            cleaner,
            flush: matches.is_present("flush"),
            hosts,
        })
    }
}
/// Reads input from stdin or a file
fn read_input(path: Option<&str>) -> Result<HashSet<String>> {
    let mut contents = HashSet::new();
    let reader: Box<dyn BufRead> = match path {
        Some(filepath) => {
            Box::new(BufReader::new(File::open(filepath).map_err(|e| {
                format!("tried to read filepath {} got {}", &filepath, e)
            })?))
        }
        None => Box::new(BufReader::new(io::stdin())),
    };

    for line in reader.lines() {
        contents.insert(line?);
    }

    Ok(contents)
}

/// Creates the Clap app to use Vita library as a cli tool
fn create_clap_app() -> clap::App<'static, 'static> {
    App::new("vita")
        .version(env!("CARGO_PKG_VERSION"))
        .about("Gather subdomains from passive sources")
        .usage("vita -d <domain.com>")
        .arg(Arg::with_name("input").index(1).required(false))
        .arg(
            Arg::with_name("file")
                .help("vita -f <roots.txt>")
                .short("f")
                .long("file"),
        )
        .arg(
            Arg::with_name("domain")
                .help("vita -d domain.com")
                .short("d")
                .long("domain"),
        )
        .arg(
            Arg::with_name("all_sources")
                .help("use sources which require an Api key")
                .short("a")
                .long("all"),
        )
        .arg(
            Arg::with_name("exclude")
                .help("Excludes sources from data collection")
                .short("e")
                .long("exclude")
                .multiple(true)
                .takes_value(true),
        )
        .arg(
            Arg::with_name("subs-only")
                .help("filter the results to only those which have the same subdomain")
                .long("subs-only"),
        )
        .arg(
            Arg::with_name("flush")
                .help(
                    "Prints results to stdout as they're received. Results will still be filtered,
                    but no deduplication will be done",
                )
                .long("flush"),
        )
        .arg(
            Arg::with_name("concurrency")
                .help("The number of domains to fetch data for concurrently")
                .short("c")
                .long("concurrency")
                .default_value("200")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("verbosity")
                .help(
                    "different levels of verbosity you can set for debugging,
                    values include: debug,info and warn",
                )
                .short("v")
                .long("verbosity")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("timeout")
                .help(
                    "connection timeouts can be useful if you don't want to wait
                    for sources like wayback archive which quite a while. Default is 10 seconds.",
                )
                .short("t")
                .long("timeout")
                .default_value("15")
                .takes_value(true),
        )
}


text:
fn main() -> Result<(), Box<dyn std::error::Error>> {
    tonic_build::configure()
        .build_server(false)
        .out_dir("proto/pb")
        .compile(&["proto/crobat.proto"], &["proto"])?;
    Ok(())
}


text:
[package]
name = "crobat"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tonic = {version = "0.3.0", features = ["tls", "transport"]}
prost = "0.6"
webpki = "0.21.3"
webpki-roots = "0.20.0"
rustls = "0.18.0"
futures-core = "0.3.8"
futures-util = "0.3"
async-stream = "0.2"
log = "0.4"
pretty_env_logger = "0.4"

[build-dependencies]
tonic-build = "0.3"


text:
#![allow(clippy::rc_buffer)]

pub mod crobat {
    include!("../proto/pb/proto.rs");
}

extern crate pretty_env_logger;
#[macro_use]
extern crate log;
use crobat::crobat_client::CrobatClient;
use crobat::Domain;
use crobat::QueryRequest;
use futures_core::stream::Stream;
use std::sync::Arc;
use tonic::transport::{Channel, ClientTlsConfig};
use tonic::Status;

pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;

pub struct Crobat {
    client: CrobatClient<Channel>,
}

impl Crobat {
    pub async fn connect() -> Result<Self> {
        trace!("building crobat client");
        let addr = "https://crobat-rpc.omnisint.io";
        match Crobat::build_tls_client(addr).await {
            Ok(conn) => Ok(Self {
                client: CrobatClient::new(conn),
            }),
            Err(e) => Err(e),
        }
    }

    async fn build_tls_client(url: &'static str) -> Result<Channel> {
        let mut config = rustls::ClientConfig::new();
        config
            .root_store
            .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
        config.alpn_protocols = vec![b"h2".to_vec()];

        let conn = Channel::from_static(url)
            .tls_config(ClientTlsConfig::new().rustls_client_config(config))?
            .connect()
            .await?;

        Ok(conn)
    }

    pub async fn get_subs(
        &mut self,
        host: Arc<String>,
    ) -> Result<impl Stream<Item = std::result::Result<Domain, Status>>> {
        trace!("querying crobat client for subdomains");
        let request = tonic::Request::new(QueryRequest {
            query: host.to_string(),
        });
        let stream = self.client.get_subdomains(request).await?.into_inner();

        Ok(stream)
    }
}


text:
// Source @Cgboal
// https://github.com/Cgboal/SonarSearch/blob/master/proto/crobat.proto
syntax = "proto3";

package proto;

service Crobat {
  rpc GetSubdomains (QueryRequest) returns (stream Domain) {}
  rpc GetTLDs (QueryRequest) returns (stream Domain) {}
  rpc ReverseDNS (QueryRequest) returns (stream Domain) {}
  rpc ReverseDNSRange (QueryRequest) returns (stream ReverseResult) {}
}

message QueryRequest {
  string query = 1;
}

message Domain {
  string domain = 1;
  string ipv4 = 2;
}

message ReverseResult {
  string ip = 1;
  repeated string domains = 2;
}


text:
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct QueryRequest {
    #[prost(string, tag = "1")]
    pub query: std::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Domain {
    #[prost(string, tag = "1")]
    pub domain: std::string::String,
    #[prost(string, tag = "2")]
    pub ipv4: std::string::String,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ReverseResult {
    #[prost(string, tag = "1")]
    pub ip: std::string::String,
    #[prost(string, repeated, tag = "2")]
    pub domains: ::std::vec::Vec<std::string::String>,
}
#[doc = r" Generated client implementations."]
pub mod crobat_client {
    #![allow(unused_variables, dead_code, missing_docs)]
    use tonic::codegen::*;
    pub struct CrobatClient<T> {
        inner: tonic::client::Grpc<T>,
    }
    impl CrobatClient<tonic::transport::Channel> {
        #[doc = r" Attempt to create a new client by connecting to a given endpoint."]
        pub async fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
        where
            D: std::convert::TryInto<tonic::transport::Endpoint>,
            D::Error: Into<StdError>,
        {
            let conn = tonic::transport::Endpoint::new(dst)?.connect().await?;
            Ok(Self::new(conn))
        }
    }
    impl<T> CrobatClient<T>
    where
        T: tonic::client::GrpcService<tonic::body::BoxBody>,
        T::ResponseBody: Body + HttpBody + Send + 'static,
        T::Error: Into<StdError>,
        <T::ResponseBody as HttpBody>::Error: Into<StdError> + Send,
    {
        pub fn new(inner: T) -> Self {
            let inner = tonic::client::Grpc::new(inner);
            Self { inner }
        }
        pub fn with_interceptor(inner: T, interceptor: impl Into<tonic::Interceptor>) -> Self {
            let inner = tonic::client::Grpc::with_interceptor(inner, interceptor);
            Self { inner }
        }
        pub async fn get_subdomains(
            &mut self,
            request: impl tonic::IntoRequest<super::QueryRequest>,
        ) -> Result<tonic::Response<tonic::codec::Streaming<super::Domain>>, tonic::Status>
        {
            self.inner.ready().await.map_err(|e| {
                tonic::Status::new(
                    tonic::Code::Unknown,
                    format!("Service was not ready: {}", e.into()),
                )
            })?;
            let codec = tonic::codec::ProstCodec::default();
            let path = http::uri::PathAndQuery::from_static("/proto.Crobat/GetSubdomains");
            self.inner
                .server_streaming(request.into_request(), path, codec)
                .await
        }
        pub async fn get_tl_ds(
            &mut self,
            request: impl tonic::IntoRequest<super::QueryRequest>,
        ) -> Result<tonic::Response<tonic::codec::Streaming<super::Domain>>, tonic::Status>
        {
            self.inner.ready().await.map_err(|e| {
                tonic::Status::new(
                    tonic::Code::Unknown,
                    format!("Service was not ready: {}", e.into()),
                )
            })?;
            let codec = tonic::codec::ProstCodec::default();
            let path = http::uri::PathAndQuery::from_static("/proto.Crobat/GetTLDs");
            self.inner
                .server_streaming(request.into_request(), path, codec)
                .await
        }
        pub async fn reverse_dns(
            &mut self,
            request: impl tonic::IntoRequest<super::QueryRequest>,
        ) -> Result<tonic::Response<tonic::codec::Streaming<super::Domain>>, tonic::Status>
        {
            self.inner.ready().await.map_err(|e| {
                tonic::Status::new(
                    tonic::Code::Unknown,
                    format!("Service was not ready: {}", e.into()),
                )
            })?;
            let codec = tonic::codec::ProstCodec::default();
            let path = http::uri::PathAndQuery::from_static("/proto.Crobat/ReverseDNS");
            self.inner
                .server_streaming(request.into_request(), path, codec)
                .await
        }
        pub async fn reverse_dns_range(
            &mut self,
            request: impl tonic::IntoRequest<super::QueryRequest>,
        ) -> Result<tonic::Response<tonic::codec::Streaming<super::ReverseResult>>, tonic::Status>
        {
            self.inner.ready().await.map_err(|e| {
                tonic::Status::new(
                    tonic::Code::Unknown,
                    format!("Service was not ready: {}", e.into()),
                )
            })?;
            let codec = tonic::codec::ProstCodec::default();
            let path = http::uri::PathAndQuery::from_static("/proto.Crobat/ReverseDNSRange");
            self.inner
                .server_streaming(request.into_request(), path, codec)
                .await
        }
    }
    impl<T: Clone> Clone for CrobatClient<T> {
        fn clone(&self) -> Self {
            Self {
                inner: self.inner.clone(),
            }
        }
    }
    impl<T> std::fmt::Debug for CrobatClient<T> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            write!(f, "CrobatClient {{ ... }}")
        }
    }
}


text:
ShaderGraphAssets
=================

Basic asset collection for Unity Shader Graph

System requirements
-------------------

- Unity 2021.3 or later
- Shader Graph 12.1 or later

How to Install
--------------

This package uses the [scoped registry] feature to resolve package
dependencies. Open the Package Manager page in the Project Settings window and
add the following entry to the Scoped Registries list:

- Name: `Keijiro`
- URL: `https://registry.npmjs.com`
- Scope: `jp.keijiro`

![Scoped Registry](https://user-images.githubusercontent.com/343936/162576797-ae39ee00-cb40-4312-aacd-3247077e7fa1.png)

Now you can install the package from My Registries page in the Package Manager
window.

![My Registries](https://user-images.githubusercontent.com/343936/162576825-4a9a443d-62f9-48d3-8a82-a3e80b486f04.png)

[scoped registry]: https://docs.unity3d.com/Manual/upm-scoped.html

repo_name: keijiro/ShaderGraphAssets

repo_language: HLSL

file_name: Simplex Noise 3D.shadersubgraph.meta


text:
name: UPM on npsjs.com
on:
  release:
    types: [created]
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v2
      with:
        registry-url: 'https://registry.npmjs.org'
    - run: npm publish
      working-directory: Packages/jp.keijiro.shadergraphassets
      env:
        NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &1
MonoBehaviour:
  m_ObjectHideFlags: 61
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 0}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: 247994e1f5a72c2419c26a37e9334c01, type: 3}
  m_Name:
  m_EditorClassIdentifier:
  m_LastMaterialVersion: 7


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &1
MonoBehaviour:
  m_ObjectHideFlags: 61
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 0}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: de02f9e1d18f588468e474319d09a723, type: 3}
  m_Name:
  m_EditorClassIdentifier:
  customInterpolatorErrorThreshold: 32
  customInterpolatorWarningThreshold: 16


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!13 &1
InputManager:
  m_ObjectHideFlags: 0
  serializedVersion: 2
  m_Axes:
  - serializedVersion: 3
    m_Name: Horizontal
    descriptiveName:
    descriptiveNegativeName:
    negativeButton: left
    positiveButton: right
    altNegativeButton: a
    altPositiveButton: d
    gravity: 3
    dead: 0.001
    sensitivity: 3
    snap: 1
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Vertical
    descriptiveName:
    descriptiveNegativeName:
    negativeButton: down
    positiveButton: up
    altNegativeButton: s
    altPositiveButton: w
    gravity: 3
    dead: 0.001
    sensitivity: 3
    snap: 1
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Fire1
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: left ctrl
    altNegativeButton:
    altPositiveButton: mouse 0
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Fire2
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: left alt
    altNegativeButton:
    altPositiveButton: mouse 1
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Fire3
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: left shift
    altNegativeButton:
    altPositiveButton: mouse 2
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Jump
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: space
    altNegativeButton:
    altPositiveButton:
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Mouse X
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton:
    altNegativeButton:
    altPositiveButton:
    gravity: 0
    dead: 0
    sensitivity: 0.1
    snap: 0
    invert: 0
    type: 1
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Mouse Y
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton:
    altNegativeButton:
    altPositiveButton:
    gravity: 0
    dead: 0
    sensitivity: 0.1
    snap: 0
    invert: 0
    type: 1
    axis: 1
    joyNum: 0
  - serializedVersion: 3
    m_Name: Mouse ScrollWheel
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton:
    altNegativeButton:
    altPositiveButton:
    gravity: 0
    dead: 0
    sensitivity: 0.1
    snap: 0
    invert: 0
    type: 1
    axis: 2
    joyNum: 0
  - serializedVersion: 3
    m_Name: Horizontal
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton:
    altNegativeButton:
    altPositiveButton:
    gravity: 0
    dead: 0.19
    sensitivity: 1
    snap: 0
    invert: 0
    type: 2
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Vertical
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton:
    altNegativeButton:
    altPositiveButton:
    gravity: 0
    dead: 0.19
    sensitivity: 1
    snap: 0
    invert: 1
    type: 2
    axis: 1
    joyNum: 0
  - serializedVersion: 3
    m_Name: Fire1
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: joystick button 0
    altNegativeButton:
    altPositiveButton:
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Fire2
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: joystick button 1
    altNegativeButton:
    altPositiveButton:
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Fire3
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: joystick button 2
    altNegativeButton:
    altPositiveButton:
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Jump
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: joystick button 3
    altNegativeButton:
    altPositiveButton:
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Submit
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: return
    altNegativeButton:
    altPositiveButton: joystick button 0
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Submit
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: enter
    altNegativeButton:
    altPositiveButton: space
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Cancel
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: escape
    altNegativeButton:
    altPositiveButton: joystick button 1
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Enable Debug Button 1
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: left ctrl
    altNegativeButton:
    altPositiveButton: joystick button 8
    gravity: 0
    dead: 0
    sensitivity: 0
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Enable Debug Button 2
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: backspace
    altNegativeButton:
    altPositiveButton: joystick button 9
    gravity: 0
    dead: 0
    sensitivity: 0
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Debug Reset
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: left alt
    altNegativeButton:
    altPositiveButton: joystick button 1
    gravity: 0
    dead: 0
    sensitivity: 0
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Debug Next
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: page down
    altNegativeButton:
    altPositiveButton: joystick button 5
    gravity: 0
    dead: 0
    sensitivity: 0
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Debug Previous
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: page up
    altNegativeButton:
    altPositiveButton: joystick button 4
    gravity: 0
    dead: 0
    sensitivity: 0
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Debug Validate
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: return
    altNegativeButton:
    altPositiveButton: joystick button 0
    gravity: 0
    dead: 0
    sensitivity: 0
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Debug Persistent
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: right shift
    altNegativeButton:
    altPositiveButton: joystick button 2
    gravity: 0
    dead: 0
    sensitivity: 0
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Debug Multiplier
    descriptiveName:
    descriptiveNegativeName:
    negativeButton:
    positiveButton: left shift
    altNegativeButton:
    altPositiveButton: joystick button 3
    gravity: 0
    dead: 0
    sensitivity: 0
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Debug Horizontal
    descriptiveName:
    descriptiveNegativeName:
    negativeButton: left
    positiveButton: right
    altNegativeButton:
    altPositiveButton:
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Debug Vertical
    descriptiveName:
    descriptiveNegativeName:
    negativeButton: down
    positiveButton: up
    altNegativeButton:
    altPositiveButton:
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 0
    axis: 0
    joyNum: 0
  - serializedVersion: 3
    m_Name: Debug Vertical
    descriptiveName:
    descriptiveNegativeName:
    negativeButton: down
    positiveButton: up
    altNegativeButton:
    altPositiveButton:
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 2
    axis: 6
    joyNum: 0
  - serializedVersion: 3
    m_Name: Debug Horizontal
    descriptiveName:
    descriptiveNegativeName:
    negativeButton: left
    positiveButton: right
    altNegativeButton:
    altPositiveButton:
    gravity: 1000
    dead: 0.001
    sensitivity: 1000
    snap: 0
    invert: 0
    type: 2
    axis: 5
    joyNum: 0
  m_UsePhysicalKeys: 0


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1386491679 &1
PresetManager:
  m_ObjectHideFlags: 0
  serializedVersion: 2
  m_DefaultPresets: {}


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!78 &1
TagManager:
  serializedVersion: 2
  tags: []
  layers:
  - Default
  - TransparentFX
  - Ignore Raycast
  -
  - Water
  - UI
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  -
  m_SortingLayers:
  - name: Default
    uniqueID: 0
    locked: 0


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!236 &1
ClusterInputManager:
  m_ObjectHideFlags: 0
  m_Inputs: []


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1045 &1
EditorBuildSettings:
  m_ObjectHideFlags: 0
  serializedVersion: 2
  m_Scenes:
  - enabled: 1
    path: Assets/Basic.unity
    guid: 539c0b9458bd58f40a4478767897661f
  m_configObjects: {}


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!5 &1
TimeManager:
  m_ObjectHideFlags: 0
  Fixed Timestep: 0.02
  Maximum Allowed Timestep: 0.33333334
  m_TimeScale: 1
  Maximum Particle Timestep: 0.03


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!387306366 &1
MemorySettings:
  m_ObjectHideFlags: 0
  m_EditorMemorySettings:
    m_MainAllocatorBlockSize: -1
    m_ThreadAllocatorBlockSize: -1
    m_MainGfxBlockSize: -1
    m_ThreadGfxBlockSize: -1
    m_CacheBlockSize: -1
    m_TypetreeBlockSize: -1
    m_ProfilerBlockSize: -1
    m_ProfilerEditorBlockSize: -1
    m_BucketAllocatorGranularity: -1
    m_BucketAllocatorBucketsCount: -1
    m_BucketAllocatorBlockSize: -1
    m_BucketAllocatorBlockCount: -1
    m_ProfilerBucketAllocatorGranularity: -1
    m_ProfilerBucketAllocatorBucketsCount: -1
    m_ProfilerBucketAllocatorBlockSize: -1
    m_ProfilerBucketAllocatorBlockCount: -1
    m_TempAllocatorSizeMain: -1
    m_JobTempAllocatorBlockSize: -1
    m_BackgroundJobTempAllocatorBlockSize: -1
    m_JobTempAllocatorReducedBlockSize: -1
    m_TempAllocatorSizeGIBakingWorker: -1
    m_TempAllocatorSizeNavMeshWorker: -1
    m_TempAllocatorSizeAudioWorker: -1
    m_TempAllocatorSizeCloudWorker: -1
    m_TempAllocatorSizeGfx: -1
    m_TempAllocatorSizeJobWorker: -1
    m_TempAllocatorSizeBackgroundWorker: -1
    m_TempAllocatorSizePreloadManager: -1
  m_PlatformMemorySettings: {}


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!129 &1
PlayerSettings:
  m_ObjectHideFlags: 0
  serializedVersion: 23
  productGUID: 8bf90527fd3096041a315ec31d64ebaf
  AndroidProfiler: 0
  AndroidFilterTouchesWhenObscured: 0
  AndroidEnableSustainedPerformanceMode: 0
  defaultScreenOrientation: 4
  targetDevice: 2
  useOnDemandResources: 0
  accelerometerFrequency: 60
  companyName: DefaultCompany
  productName: ShaderGraphAssets
  defaultCursor: {fileID: 0}
  cursorHotspot: {x: 0, y: 0}
  m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1}
  m_ShowUnitySplashScreen: 0
  m_ShowUnitySplashLogo: 1
  m_SplashScreenOverlayOpacity: 1
  m_SplashScreenAnimation: 1
  m_SplashScreenLogoStyle: 1
  m_SplashScreenDrawMode: 0
  m_SplashScreenBackgroundAnimationZoom: 1
  m_SplashScreenLogoAnimationZoom: 1
  m_SplashScreenBackgroundLandscapeAspect: 1
  m_SplashScreenBackgroundPortraitAspect: 1
  m_SplashScreenBackgroundLandscapeUvs:
    serializedVersion: 2
    x: 0
    y: 0
    width: 1
    height: 1
  m_SplashScreenBackgroundPortraitUvs:
    serializedVersion: 2
    x: 0
    y: 0
    width: 1
    height: 1
  m_SplashScreenLogos: []
  m_VirtualRealitySplashScreen: {fileID: 0}
  m_HolographicTrackingLossScreen: {fileID: 0}
  defaultScreenWidth: 1920
  defaultScreenHeight: 1080
  defaultScreenWidthWeb: 960
  defaultScreenHeightWeb: 600
  m_StereoRenderingPath: 0
  m_ActiveColorSpace: 0
  m_MTRendering: 1
  mipStripping: 0
  numberOfMipsStripped: 0
  m_StackTraceTypes: 010000000100000001000000010000000100000001000000
  iosShowActivityIndicatorOnLoading: -1
  androidShowActivityIndicatorOnLoading: -1
  iosUseCustomAppBackgroundBehavior: 0
  iosAllowHTTPDownload: 1
  allowedAutorotateToPortrait: 1
  allowedAutorotateToPortraitUpsideDown: 1
  allowedAutorotateToLandscapeRight: 1
  allowedAutorotateToLandscapeLeft: 1
  useOSAutorotation: 1
  use32BitDisplayBuffer: 1
  preserveFramebufferAlpha: 0
  disableDepthAndStencilBuffers: 0
  androidStartInFullscreen: 1
  androidRenderOutsideSafeArea: 1
  androidUseSwappy: 1
  androidBlitType: 0
  androidResizableWindow: 0
  androidDefaultWindowWidth: 1920
  androidDefaultWindowHeight: 1080
  androidMinimumWindowWidth: 400
  androidMinimumWindowHeight: 300
  androidFullscreenMode: 1
  defaultIsNativeResolution: 1
  macRetinaSupport: 1
  runInBackground: 0
  captureSingleScreen: 0
  muteOtherAudioSources: 0
  Prepare IOS For Recording: 0
  Force IOS Speakers When Recording: 0
  deferSystemGesturesMode: 0
  hideHomeButton: 0
  submitAnalytics: 1
  usePlayerLog: 1
  bakeCollisionMeshes: 0
  forceSingleInstance: 0
  useFlipModelSwapchain: 1
  resizableWindow: 0
  useMacAppStoreValidation: 0
  macAppStoreCategory: public.app-category.games
  gpuSkinning: 1
  xboxPIXTextureCapture: 0
  xboxEnableAvatar: 0
  xboxEnableKinect: 0
  xboxEnableKinectAutoTracking: 0
  xboxEnableFitness: 0
  visibleInBackground: 1
  allowFullscreenSwitch: 1
  fullscreenMode: 3
  xboxSpeechDB: 0
  xboxEnableHeadOrientation: 0
  xboxEnableGuest: 0
  xboxEnablePIXSampling: 0
  metalFramebufferOnly: 0
  xboxOneResolution: 0
  xboxOneSResolution: 0
  xboxOneXResolution: 3
  xboxOneMonoLoggingLevel: 0
  xboxOneLoggingLevel: 1
  xboxOneDisableEsram: 0
  xboxOneEnableTypeOptimization: 0
  xboxOnePresentImmediateThreshold: 0
  switchQueueCommandMemory: 0
  switchQueueControlMemory: 16384
  switchQueueComputeMemory: 262144
  switchNVNShaderPoolsGranularity: 33554432
  switchNVNDefaultPoolsGranularity: 16777216
  switchNVNOtherPoolsGranularity: 16777216
  switchNVNMaxPublicTextureIDCount: 0
  switchNVNMaxPublicSamplerIDCount: 0
  stadiaPresentMode: 0
  stadiaTargetFramerate: 0
  vulkanNumSwapchainBuffers: 3
  vulkanEnableSetSRGBWrite: 0
  vulkanEnablePreTransform: 1
  vulkanEnableLateAcquireNextImage: 0
  vulkanEnableCommandBufferRecycling: 1
  m_SupportedAspectRatios:
    4:3: 1
    5:4: 1
    16:10: 1
    16:9: 1
    Others: 1
  bundleVersion: 0.1
  preloadedAssets: []
  metroInputSource: 0
  wsaTransparentSwapchain: 0
  m_HolographicPauseOnTrackingLoss: 1
  xboxOneDisableKinectGpuReservation: 1
  xboxOneEnable7thCore: 1
  vrSettings:
    enable360StereoCapture: 0
  isWsaHolographicRemotingEnabled: 0
  enableFrameTimingStats: 0
  useHDRDisplay: 0
  D3DHDRBitDepth: 0
  m_ColorGamuts: 00000000
  targetPixelDensity: 30
  resolutionScalingMode: 0
  androidSupportedAspectRatio: 1
  androidMaxAspectRatio: 2.1
  applicationIdentifier:
    Standalone: com.DefaultCompany.ShaderGraphAssets
  buildNumber:
    Standalone: 0
    iPhone: 0
    tvOS: 0
  overrideDefaultApplicationIdentifier: 0
  AndroidBundleVersionCode: 1
  AndroidMinSdkVersion: 22
  AndroidTargetSdkVersion: 0
  AndroidPreferredInstallLocation: 1
  aotOptions:
  stripEngineCode: 1
  iPhoneStrippingLevel: 0
  iPhoneScriptCallOptimization: 0
  ForceInternetPermission: 0
  ForceSDCardPermission: 0
  CreateWallpaper: 0
  APKExpansionFiles: 0
  keepLoadedShadersAlive: 0
  StripUnusedMeshComponents: 1
  VertexChannelCompressionMask: 4054
  iPhoneSdkVersion: 988
  iOSTargetOSVersionString: 11.0
  tvOSSdkVersion: 0
  tvOSRequireExtendedGameController: 0
  tvOSTargetOSVersionString: 11.0
  uIPrerenderedIcon: 0
  uIRequiresPersistentWiFi: 0
  uIRequiresFullScreen: 1
  uIStatusBarHidden: 1
  uIExitOnSuspend: 0
  uIStatusBarStyle: 0
  appleTVSplashScreen: {fileID: 0}
  appleTVSplashScreen2x: {fileID: 0}
  tvOSSmallIconLayers: []
  tvOSSmallIconLayers2x: []
  tvOSLargeIconLayers: []
  tvOSLargeIconLayers2x: []
  tvOSTopShelfImageLayers: []
  tvOSTopShelfImageLayers2x: []
  tvOSTopShelfImageWideLayers: []
  tvOSTopShelfImageWideLayers2x: []
  iOSLaunchScreenType: 0
  iOSLaunchScreenPortrait: {fileID: 0}
  iOSLaunchScreenLandscape: {fileID: 0}
  iOSLaunchScreenBackgroundColor:
    serializedVersion: 2
    rgba: 0
  iOSLaunchScreenFillPct: 100
  iOSLaunchScreenSize: 100
  iOSLaunchScreenCustomXibPath:
  iOSLaunchScreeniPadType: 0
  iOSLaunchScreeniPadImage: {fileID: 0}
  iOSLaunchScreeniPadBackgroundColor:
    serializedVersion: 2
    rgba: 0
  iOSLaunchScreeniPadFillPct: 100
  iOSLaunchScreeniPadSize: 100
  iOSLaunchScreeniPadCustomXibPath:
  iOSLaunchScreenCustomStoryboardPath:
  iOSLaunchScreeniPadCustomStoryboardPath:
  iOSDeviceRequirements: []
  iOSURLSchemes: []
  macOSURLSchemes: []
  iOSBackgroundModes: 0
  iOSMetalForceHardShadows: 0
  metalEditorSupport: 1
  metalAPIValidation: 1
  iOSRenderExtraFrameOnPause: 0
  iosCopyPluginsCodeInsteadOfSymlink: 0
  appleDeveloperTeamID:
  iOSManualSigningProvisioningProfileID:
  tvOSManualSigningProvisioningProfileID:
  iOSManualSigningProvisioningProfileType: 0
  tvOSManualSigningProvisioningProfileType: 0
  appleEnableAutomaticSigning: 0
  iOSRequireARKit: 0
  iOSAutomaticallyDetectAndAddCapabilities: 1
  appleEnableProMotion: 0
  shaderPrecisionModel: 0
  clonedFromGUID: c0afd0d1d80e3634a9dac47e8a0426ea
  templatePackageId: com.unity.template.3d@8.0.0
  templateDefaultScene: Assets/Scenes/SampleScene.unity
  useCustomMainManifest: 0
  useCustomLauncherManifest: 0
  useCustomMainGradleTemplate: 0
  useCustomLauncherGradleManifest: 0
  useCustomBaseGradleTemplate: 0
  useCustomGradlePropertiesTemplate: 0
  useCustomProguardFile: 0
  AndroidTargetArchitectures: 1
  AndroidTargetDevices: 0
  AndroidSplashScreenScale: 0
  androidSplashScreen: {fileID: 0}
  AndroidKeystoreName:
  AndroidKeyaliasName:
  AndroidBuildApkPerCpuArchitecture: 0
  AndroidTVCompatibility: 0
  AndroidIsGame: 1
  AndroidEnableTango: 0
  androidEnableBanner: 1
  androidUseLowAccuracyLocation: 0
  androidUseCustomKeystore: 0
  m_AndroidBanners:
  - width: 320
    height: 180
    banner: {fileID: 0}
  androidGamepadSupportLevel: 0
  chromeosInputEmulation: 1
  AndroidMinifyWithR8: 0
  AndroidMinifyRelease: 0
  AndroidMinifyDebug: 0
  AndroidValidateAppBundleSize: 1
  AndroidAppBundleSizeToValidate: 150
  m_BuildTargetIcons: []
  m_BuildTargetPlatformIcons:
  - m_BuildTarget: iPhone
    m_Icons:
    - m_Textures: []
      m_Width: 180
      m_Height: 180
      m_Kind: 0
      m_SubKind: iPhone
    - m_Textures: []
      m_Width: 120
      m_Height: 120
      m_Kind: 0
      m_SubKind: iPhone
    - m_Textures: []
      m_Width: 167
      m_Height: 167
      m_Kind: 0
      m_SubKind: iPad
    - m_Textures: []
      m_Width: 152
      m_Height: 152
      m_Kind: 0
      m_SubKind: iPad
    - m_Textures: []
      m_Width: 76
      m_Height: 76
      m_Kind: 0
      m_SubKind: iPad
    - m_Textures: []
      m_Width: 120
      m_Height: 120
      m_Kind: 3
      m_SubKind: iPhone
    - m_Textures: []
      m_Width: 80
      m_Height: 80
      m_Kind: 3
      m_SubKind: iPhone
    - m_Textures: []
      m_Width: 80
      m_Height: 80
      m_Kind: 3
      m_SubKind: iPad
    - m_Textures: []
      m_Width: 40
      m_Height: 40
      m_Kind: 3
      m_SubKind: iPad
    - m_Textures: []
      m_Width: 87
      m_Height: 87
      m_Kind: 1
      m_SubKind: iPhone
    - m_Textures: []
      m_Width: 58
      m_Height: 58
      m_Kind: 1
      m_SubKind: iPhone
    - m_Textures: []
      m_Width: 29
      m_Height: 29
      m_Kind: 1
      m_SubKind: iPhone
    - m_Textures: []
      m_Width: 58
      m_Height: 58
      m_Kind: 1
      m_SubKind: iPad
    - m_Textures: []
      m_Width: 29
      m_Height: 29
      m_Kind: 1
      m_SubKind: iPad
    - m_Textures: []
      m_Width: 60
      m_Height: 60
      m_Kind: 2
      m_SubKind: iPhone
    - m_Textures: []
      m_Width: 40
      m_Height: 40
      m_Kind: 2
      m_SubKind: iPhone
    - m_Textures: []
      m_Width: 40
      m_Height: 40
      m_Kind: 2
      m_SubKind: iPad
    - m_Textures: []
      m_Width: 20
      m_Height: 20
      m_Kind: 2
      m_SubKind: iPad
    - m_Textures: []
      m_Width: 1024
      m_Height: 1024
      m_Kind: 4
      m_SubKind: App Store
  m_BuildTargetBatching:
  - m_BuildTarget: Standalone
    m_StaticBatching: 1
    m_DynamicBatching: 0
  - m_BuildTarget: tvOS
    m_StaticBatching: 1
    m_DynamicBatching: 0
  - m_BuildTarget: Android
    m_StaticBatching: 1
    m_DynamicBatching: 0
  - m_BuildTarget: iPhone
    m_StaticBatching: 1
    m_DynamicBatching: 0
  - m_BuildTarget: WebGL
    m_StaticBatching: 0
    m_DynamicBatching: 0
  m_BuildTargetGraphicsJobs:
  - m_BuildTarget: MacStandaloneSupport
    m_GraphicsJobs: 0
  - m_BuildTarget: Switch
    m_GraphicsJobs: 1
  - m_BuildTarget: MetroSupport
    m_GraphicsJobs: 1
  - m_BuildTarget: AppleTVSupport
    m_GraphicsJobs: 0
  - m_BuildTarget: BJMSupport
    m_GraphicsJobs: 1
  - m_BuildTarget: LinuxStandaloneSupport
    m_GraphicsJobs: 1
  - m_BuildTarget: PS4Player
    m_GraphicsJobs: 1
  - m_BuildTarget: iOSSupport
    m_GraphicsJobs: 0
  - m_BuildTarget: WindowsStandaloneSupport
    m_GraphicsJobs: 1
  - m_BuildTarget: XboxOnePlayer
    m_GraphicsJobs: 1
  - m_BuildTarget: LuminSupport
    m_GraphicsJobs: 0
  - m_BuildTarget: AndroidPlayer
    m_GraphicsJobs: 0
  - m_BuildTarget: WebGLSupport
    m_GraphicsJobs: 0
  m_BuildTargetGraphicsJobMode:
  - m_BuildTarget: PS4Player
    m_GraphicsJobMode: 0
  - m_BuildTarget: XboxOnePlayer
    m_GraphicsJobMode: 0
  m_BuildTargetGraphicsAPIs:
  - m_BuildTarget: AndroidPlayer
    m_APIs: 150000000b000000
    m_Automatic: 1
  - m_BuildTarget: iOSSupport
    m_APIs: 10000000
    m_Automatic: 1
  - m_BuildTarget: AppleTVSupport
    m_APIs: 10000000
    m_Automatic: 1
  - m_BuildTarget: WebGLSupport
    m_APIs: 0b000000
    m_Automatic: 1
  m_BuildTargetVRSettings:
  - m_BuildTarget: Standalone
    m_Enabled: 0
    m_Devices:
    - Oculus
    - OpenVR
  openGLRequireES31: 0
  openGLRequireES31AEP: 0
  openGLRequireES32: 0
  m_TemplateCustomTags: {}
  mobileMTRendering:
    Android: 1
    iPhone: 1
    tvOS: 1
  m_BuildTargetGroupLightmapEncodingQuality:
  - m_BuildTarget: Android
    m_EncodingQuality: 1
  - m_BuildTarget: iPhone
    m_EncodingQuality: 1
  - m_BuildTarget: tvOS
    m_EncodingQuality: 1
  m_BuildTargetGroupLightmapSettings: []
  m_BuildTargetNormalMapEncoding:
  - m_BuildTarget: Android
    m_Encoding: 1
  - m_BuildTarget: iPhone
    m_Encoding: 1
  - m_BuildTarget: tvOS
    m_Encoding: 1
  m_BuildTargetDefaultTextureCompressionFormat:
  - m_BuildTarget: Android
    m_Format: 3
  playModeTestRunnerEnabled: 0
  runPlayModeTestAsEditModeTest: 0
  actionOnDotNetUnhandledException: 1
  enableInternalProfiler: 0
  logObjCUncaughtExceptions: 1
  enableCrashReportAPI: 0
  cameraUsageDescription:
  locationUsageDescription:
  microphoneUsageDescription:
  bluetoothUsageDescription:
  switchNMETAOverride:
  switchNetLibKey:
  switchSocketMemoryPoolSize: 6144
  switchSocketAllocatorPoolSize: 128
  switchSocketConcurrencyLimit: 14
  switchScreenResolutionBehavior: 2
  switchUseCPUProfiler: 0
  switchUseGOLDLinker: 0
  switchLTOSetting: 0
  switchApplicationID: 0x01004b9000490000
  switchNSODependencies:
  switchTitleNames_0:
  switchTitleNames_1:
  switchTitleNames_2:
  switchTitleNames_3:
  switchTitleNames_4:
  switchTitleNames_5:
  switchTitleNames_6:
  switchTitleNames_7:
  switchTitleNames_8:
  switchTitleNames_9:
  switchTitleNames_10:
  switchTitleNames_11:
  switchTitleNames_12:
  switchTitleNames_13:
  switchTitleNames_14:
  switchTitleNames_15:
  switchPublisherNames_0:
  switchPublisherNames_1:
  switchPublisherNames_2:
  switchPublisherNames_3:
  switchPublisherNames_4:
  switchPublisherNames_5:
  switchPublisherNames_6:
  switchPublisherNames_7:
  switchPublisherNames_8:
  switchPublisherNames_9:
  switchPublisherNames_10:
  switchPublisherNames_11:
  switchPublisherNames_12:
  switchPublisherNames_13:
  switchPublisherNames_14:
  switchPublisherNames_15:
  switchIcons_0: {fileID: 0}
  switchIcons_1: {fileID: 0}
  switchIcons_2: {fileID: 0}
  switchIcons_3: {fileID: 0}
  switchIcons_4: {fileID: 0}
  switchIcons_5: {fileID: 0}
  switchIcons_6: {fileID: 0}
  switchIcons_7: {fileID: 0}
  switchIcons_8: {fileID: 0}
  switchIcons_9: {fileID: 0}
  switchIcons_10: {fileID: 0}
  switchIcons_11: {fileID: 0}
  switchIcons_12: {fileID: 0}
  switchIcons_13: {fileID: 0}
  switchIcons_14: {fileID: 0}
  switchIcons_15: {fileID: 0}
  switchSmallIcons_0: {fileID: 0}
  switchSmallIcons_1: {fileID: 0}
  switchSmallIcons_2: {fileID: 0}
  switchSmallIcons_3: {fileID: 0}
  switchSmallIcons_4: {fileID: 0}
  switchSmallIcons_5: {fileID: 0}
  switchSmallIcons_6: {fileID: 0}
  switchSmallIcons_7: {fileID: 0}
  switchSmallIcons_8: {fileID: 0}
  switchSmallIcons_9: {fileID: 0}
  switchSmallIcons_10: {fileID: 0}
  switchSmallIcons_11: {fileID: 0}
  switchSmallIcons_12: {fileID: 0}
  switchSmallIcons_13: {fileID: 0}
  switchSmallIcons_14: {fileID: 0}
  switchSmallIcons_15: {fileID: 0}
  switchManualHTML:
  switchAccessibleURLs:
  switchLegalInformation:
  switchMainThreadStackSize: 1048576
  switchPresenceGroupId:
  switchLogoHandling: 0
  switchReleaseVersion: 0
  switchDisplayVersion: 1.0.0
  switchStartupUserAccount: 0
  switchTouchScreenUsage: 0
  switchSupportedLanguagesMask: 0
  switchLogoType: 0
  switchApplicationErrorCodeCategory:
  switchUserAccountSaveDataSize: 0
  switchUserAccountSaveDataJournalSize: 0
  switchApplicationAttribute: 0
  switchCardSpecSize: -1
  switchCardSpecClock: -1
  switchRatingsMask: 0
  switchRatingsInt_0: 0
  switchRatingsInt_1: 0
  switchRatingsInt_2: 0
  switchRatingsInt_3: 0
  switchRatingsInt_4: 0
  switchRatingsInt_5: 0
  switchRatingsInt_6: 0
  switchRatingsInt_7: 0
  switchRatingsInt_8: 0
  switchRatingsInt_9: 0
  switchRatingsInt_10: 0
  switchRatingsInt_11: 0
  switchRatingsInt_12: 0
  switchLocalCommunicationIds_0:
  switchLocalCommunicationIds_1:
  switchLocalCommunicationIds_2:
  switchLocalCommunicationIds_3:
  switchLocalCommunicationIds_4:
  switchLocalCommunicationIds_5:
  switchLocalCommunicationIds_6:
  switchLocalCommunicationIds_7:
  switchParentalControl: 0
  switchAllowsScreenshot: 1
  switchAllowsVideoCapturing: 1
  switchAllowsRuntimeAddOnContentInstall: 0
  switchDataLossConfirmation: 0
  switchUserAccountLockEnabled: 0
  switchSystemResourceMemory: 16777216
  switchSupportedNpadStyles: 22
  switchNativeFsCacheSize: 32
  switchIsHoldTypeHorizontal: 0
  switchSupportedNpadCount: 8
  switchSocketConfigEnabled: 0
  switchTcpInitialSendBufferSize: 32
  switchTcpInitialReceiveBufferSize: 64
  switchTcpAutoSendBufferSizeMax: 256
  switchTcpAutoReceiveBufferSizeMax: 256
  switchUdpSendBufferSize: 9
  switchUdpReceiveBufferSize: 42
  switchSocketBufferEfficiency: 4
  switchSocketInitializeEnabled: 1
  switchNetworkInterfaceManagerInitializeEnabled: 1
  switchPlayerConnectionEnabled: 1
  switchUseNewStyleFilepaths: 0
  switchUseMicroSleepForYield: 1
  switchEnableRamDiskSupport: 0
  switchMicroSleepForYieldTime: 25
  switchRamDiskSpaceSize: 12
  ps4NPAgeRating: 12
  ps4NPTitleSecret:
  ps4NPTrophyPackPath:
  ps4ParentalLevel: 11
  ps4ContentID: ED1633-NPXX51362_00-0000000000000000
  ps4Category: 0
  ps4MasterVersion: 01.00
  ps4AppVersion: 01.00
  ps4AppType: 0
  ps4ParamSfxPath:
  ps4VideoOutPixelFormat: 0
  ps4VideoOutInitialWidth: 1920
  ps4VideoOutBaseModeInitialWidth: 1920
  ps4VideoOutReprojectionRate: 60
  ps4PronunciationXMLPath:
  ps4PronunciationSIGPath:
  ps4BackgroundImagePath:
  ps4StartupImagePath:
  ps4StartupImagesFolder:
  ps4IconImagesFolder:
  ps4SaveDataImagePath:
  ps4SdkOverride:
  ps4BGMPath:
  ps4ShareFilePath:
  ps4ShareOverlayImagePath:
  ps4PrivacyGuardImagePath:
  ps4ExtraSceSysFile:
  ps4NPtitleDatPath:
  ps4RemotePlayKeyAssignment: -1
  ps4RemotePlayKeyMappingDir:
  ps4PlayTogetherPlayerCount: 0
  ps4EnterButtonAssignment: 1
  ps4ApplicationParam1: 0
  ps4ApplicationParam2: 0
  ps4ApplicationParam3: 0
  ps4ApplicationParam4: 0
  ps4DownloadDataSize: 0
  ps4GarlicHeapSize: 2048
  ps4ProGarlicHeapSize: 2560
  playerPrefsMaxSize: 32768
  ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ
  ps4pnSessions: 1
  ps4pnPresence: 1
  ps4pnFriends: 1
  ps4pnGameCustomData: 1
  playerPrefsSupport: 0
  enableApplicationExit: 0
  resetTempFolder: 1
  restrictedAudioUsageRights: 0
  ps4UseResolutionFallback: 0
  ps4ReprojectionSupport: 0
  ps4UseAudio3dBackend: 0
  ps4UseLowGarlicFragmentationMode: 1
  ps4SocialScreenEnabled: 0
  ps4ScriptOptimizationLevel: 0
  ps4Audio3dVirtualSpeakerCount: 14
  ps4attribCpuUsage: 0
  ps4PatchPkgPath:
  ps4PatchLatestPkgPath:
  ps4PatchChangeinfoPath:
  ps4PatchDayOne: 0
  ps4attribUserManagement: 0
  ps4attribMoveSupport: 0
  ps4attrib3DSupport: 0
  ps4attribShareSupport: 0
  ps4attribExclusiveVR: 0
  ps4disableAutoHideSplash: 0
  ps4videoRecordingFeaturesUsed: 0
  ps4contentSearchFeaturesUsed: 0
  ps4CompatibilityPS5: 0
  ps4GPU800MHz: 1
  ps4attribEyeToEyeDistanceSettingVR: 0
  ps4IncludedModules: []
  ps4attribVROutputEnabled: 0
  monoEnv:
  splashScreenBackgroundSourceLandscape: {fileID: 0}
  splashScreenBackgroundSourcePortrait: {fileID: 0}
  blurSplashScreenBackground: 1
  spritePackerPolicy:
  webGLMemorySize: 16
  webGLExceptionSupport: 1
  webGLNameFilesAsHashes: 0
  webGLDataCaching: 1
  webGLDebugSymbols: 0
  webGLEmscriptenArgs:
  webGLModulesDirectory:
  webGLTemplate: APPLICATION:Default
  webGLAnalyzeBuildSize: 0
  webGLUseEmbeddedResources: 0
  webGLCompressionFormat: 1
  webGLWasmArithmeticExceptions: 0
  webGLLinkerTarget: 1
  webGLThreadsSupport: 0
  webGLDecompressionFallback: 0
  scriptingDefineSymbols: {}
  additionalCompilerArguments: {}
  platformArchitecture: {}
  scriptingBackend: {}
  il2cppCompilerConfiguration: {}
  managedStrippingLevel: {}
  incrementalIl2cppBuild: {}
  suppressCommonWarnings: 1
  allowUnsafeCode: 0
  useDeterministicCompilation: 1
  enableRoslynAnalyzers: 1
  additionalIl2CppArgs:
  scriptingRuntimeVersion: 1
  gcIncremental: 1
  assemblyVersionValidation: 1
  gcWBarrierValidation: 0
  apiCompatibilityLevelPerPlatform: {}
  m_RenderingPath: 1
  m_MobileRenderingPath: 1
  metroPackageName: Template_3D
  metroPackageVersion:
  metroCertificatePath:
  metroCertificatePassword:
  metroCertificateSubject:
  metroCertificateIssuer:
  metroCertificateNotAfter: 0000000000000000
  metroApplicationDescription: Template_3D
  wsaImages: {}
  metroTileShortName:
  metroTileShowName: 0
  metroMediumTileShowName: 0
  metroLargeTileShowName: 0
  metroWideTileShowName: 0
  metroSupportStreamingInstall: 0
  metroLastRequiredScene: 0
  metroDefaultTileSize: 1
  metroTileForegroundText: 2
  metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0}
  metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1}
  metroSplashScreenUseBackgroundColor: 0
  platformCapabilities: {}
  metroTargetDeviceFamilies: {}
  metroFTAName:
  metroFTAFileTypes: []
  metroProtocolName:
  XboxOneProductId:
  XboxOneUpdateKey:
  XboxOneSandboxId:
  XboxOneContentId:
  XboxOneTitleId:
  XboxOneSCId:
  XboxOneGameOsOverridePath:
  XboxOnePackagingOverridePath:
  XboxOneAppManifestOverridePath:
  XboxOneVersion: 1.0.0.0
  XboxOnePackageEncryption: 0
  XboxOnePackageUpdateGranularity: 2
  XboxOneDescription:
  XboxOneLanguage:
  - enus
  XboxOneCapability: []
  XboxOneGameRating: {}
  XboxOneIsContentPackage: 0
  XboxOneEnhancedXboxCompatibilityMode: 0
  XboxOneEnableGPUVariability: 1
  XboxOneSockets: {}
  XboxOneSplashScreen: {fileID: 0}
  XboxOneAllowedProductIds: []
  XboxOnePersistentLocalStorageSize: 0
  XboxOneXTitleMemory: 8
  XboxOneOverrideIdentityName:
  XboxOneOverrideIdentityPublisher:
  vrEditorSettings: {}
  cloudServicesEnabled:
    UNet: 1
  luminIcon:
    m_Name:
    m_ModelFolderPath:
    m_PortalFolderPath:
  luminCert:
    m_CertPath:
    m_SignPackage: 1
  luminIsChannelApp: 0
  luminVersion:
    m_VersionCode: 1
    m_VersionName:
  apiCompatibilityLevel: 6
  activeInputHandler: 0
  cloudProjectId:
  framebufferDepthMemorylessMode: 0
  qualitySettingsNames: []
  projectName:
  organizationId:
  cloudEnabled: 0
  legacyClampBlendShapeWeights: 0
  playerDataPath:
  forceSRGBBlit: 1
  virtualTexturingSupportEnabled: 0


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!310 &1
UnityConnectSettings:
  m_ObjectHideFlags: 0
  serializedVersion: 1
  m_Enabled: 0
  m_TestMode: 0
  m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events
  m_EventUrl: https://cdp.cloud.unity3d.com/v1/events
  m_ConfigUrl: https://config.uca.cloud.unity3d.com
  m_DashboardUrl: https://dashboard.unity3d.com
  m_TestInitMode: 0
  CrashReportingSettings:
    m_EventUrl: https://perf-events.cloud.unity3d.com
    m_Enabled: 0
    m_LogBufferSize: 10
    m_CaptureEditorExceptions: 1
  UnityPurchasingSettings:
    m_Enabled: 0
    m_TestMode: 0
  UnityAnalyticsSettings:
    m_Enabled: 0
    m_TestMode: 0
    m_InitializeOnStartup: 1
  UnityAdsSettings:
    m_Enabled: 0
    m_InitializeOnStartup: 1
    m_TestMode: 0
    m_IosGameId:
    m_AndroidGameId:
    m_GameIds: {}
    m_GameId:
  PerformanceReportingSettings:
    m_Enabled: 0


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!937362698 &1
VFXManager:
  m_ObjectHideFlags: 0
  m_IndirectShader: {fileID: 0}
  m_CopyBufferShader: {fileID: 0}
  m_SortShader: {fileID: 0}
  m_StripUpdateShader: {fileID: 0}
  m_RenderPipeSettingsPath:
  m_FixedTimeStep: 0.016666668
  m_MaxDeltaTime: 0.05


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!19 &1
Physics2DSettings:
  m_ObjectHideFlags: 0
  serializedVersion: 4
  m_Gravity: {x: 0, y: -9.81}
  m_DefaultMaterial: {fileID: 0}
  m_VelocityIterations: 8
  m_PositionIterations: 3
  m_VelocityThreshold: 1
  m_MaxLinearCorrection: 0.2
  m_MaxAngularCorrection: 8
  m_MaxTranslationSpeed: 100
  m_MaxRotationSpeed: 360
  m_BaumgarteScale: 0.2
  m_BaumgarteTimeOfImpactScale: 0.75
  m_TimeToSleep: 0.5
  m_LinearSleepTolerance: 0.01
  m_AngularSleepTolerance: 2
  m_DefaultContactOffset: 0.01
  m_JobOptions:
    serializedVersion: 2
    useMultithreading: 0
    useConsistencySorting: 0
    m_InterpolationPosesPerJob: 100
    m_NewContactsPerJob: 30
    m_CollideContactsPerJob: 100
    m_ClearFlagsPerJob: 200
    m_ClearBodyForcesPerJob: 200
    m_SyncDiscreteFixturesPerJob: 50
    m_SyncContinuousFixturesPerJob: 50
    m_FindNearestContactsPerJob: 100
    m_UpdateTriggerContactsPerJob: 100
    m_IslandSolverCostThreshold: 100
    m_IslandSolverBodyCostScale: 1
    m_IslandSolverContactCostScale: 10
    m_IslandSolverJointCostScale: 10
    m_IslandSolverBodiesPerJob: 50
    m_IslandSolverContactsPerJob: 50
  m_AutoSimulation: 1
  m_QueriesHitTriggers: 1
  m_QueriesStartInColliders: 1
  m_CallbacksOnDisable: 1
  m_ReuseCollisionCallbacks: 1
  m_AutoSyncTransforms: 0
  m_AlwaysShowColliders: 0
  m_ShowColliderSleep: 1
  m_ShowColliderContacts: 0
  m_ShowColliderAABB: 0
  m_ContactArrowScale: 0.2
  m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412}
  m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432}
  m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745}
  m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804}
  m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!30 &1
GraphicsSettings:
  m_ObjectHideFlags: 0
  serializedVersion: 14
  m_Deferred:
    m_Mode: 1
    m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}
  m_DeferredReflections:
    m_Mode: 1
    m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0}
  m_ScreenSpaceShadows:
    m_Mode: 1
    m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0}
  m_LegacyDeferred:
    m_Mode: 1
    m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0}
  m_DepthNormals:
    m_Mode: 1
    m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0}
  m_MotionVectors:
    m_Mode: 1
    m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0}
  m_LightHalo:
    m_Mode: 1
    m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0}
  m_LensFlare:
    m_Mode: 1
    m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0}
  m_VideoShadersIncludeMode: 2
  m_AlwaysIncludedShaders:
  - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
  - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0}
  - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0}
  - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
  - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
  - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
  m_PreloadedShaders: []
  m_PreloadShadersBatchTimeLimit: -1
  m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
  m_CustomRenderPipeline: {fileID: 11400000, guid: 8d048ffffeb24584f8d69b3427c3aeae, type: 2}
  m_TransparencySortMode: 0
  m_TransparencySortAxis: {x: 0, y: 0, z: 1}
  m_DefaultRenderingPath: 1
  m_DefaultMobileRenderingPath: 1
  m_TierSettings: []
  m_LightmapStripping: 0
  m_FogStripping: 0
  m_InstancingStripping: 0
  m_LightmapKeepPlain: 1
  m_LightmapKeepDirCombined: 1
  m_LightmapKeepDynamicPlain: 1
  m_LightmapKeepDynamicDirCombined: 1
  m_LightmapKeepShadowMask: 1
  m_LightmapKeepSubtractive: 1
  m_FogKeepLinear: 1
  m_FogKeepExp: 1
  m_FogKeepExp2: 1
  m_AlbedoSwatchInfos: []
  m_LightsUseLinearIntensity: 0
  m_LightsUseColorTemperature: 1
  m_DefaultRenderingLayerMask: 1
  m_LogWhenShaderIsCompiled: 0
  m_SRPDefaultSettings:
    UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: 0604d54d04ed3ba4b9fa6487dcc6c289, type: 2}


text:
m_EditorVersion: 2022.2.14f1
m_EditorVersionWithRevision: 2022.2.14f1 (b2c9b1ac6cc0)


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!55 &1
PhysicsManager:
  m_ObjectHideFlags: 0
  serializedVersion: 11
  m_Gravity: {x: 0, y: -9.81, z: 0}
  m_DefaultMaterial: {fileID: 0}
  m_BounceThreshold: 2
  m_SleepThreshold: 0.005
  m_DefaultContactOffset: 0.01
  m_DefaultSolverIterations: 6
  m_DefaultSolverVelocityIterations: 1
  m_QueriesHitBackfaces: 0
  m_QueriesHitTriggers: 1
  m_EnableAdaptiveForce: 0
  m_ClothInterCollisionDistance: 0
  m_ClothInterCollisionStiffness: 0
  m_ContactsGeneration: 1
  m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
  m_AutoSimulation: 1
  m_AutoSyncTransforms: 0
  m_ReuseCollisionCallbacks: 1
  m_ClothInterCollisionSettingsToggle: 0
  m_ContactPairsMode: 0
  m_BroadphaseType: 0
  m_WorldBounds:
    m_Center: {x: 0, y: 0, z: 0}
    m_Extent: {x: 250, y: 250, z: 250}
  m_WorldSubdivisions: 8
  m_FrictionType: 0
  m_EnableEnhancedDeterminism: 0
  m_EnableUnifiedHeightmaps: 1
  m_DefaultMaxAngluarSpeed: 7


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &1
MonoBehaviour:
  m_ObjectHideFlags: 61
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 0}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0}
  m_Name:
  m_EditorClassIdentifier:
  m_EnablePreReleasePackages: 1
  m_EnablePackageDependencies: 1
  m_AdvancedSettingsExpanded: 1
  m_ScopedRegistriesSettingsExpanded: 1
  m_SeeAllPackageVersions: 0
  oneTimeWarningShown: 1
  m_Registries:
  - m_Id: main
    m_Name:
    m_Url: https://packages.unity.com
    m_Scopes: []
    m_IsDefault: 1
    m_Capabilities: 7
    m_ConfigSource: 0
  - m_Id: scoped:project:Keijiro
    m_Name: Keijiro
    m_Url: https://registry.npmjs.com
    m_Scopes:
    - jp.keijiro
    m_IsDefault: 0
    m_Capabilities: 0
    m_ConfigSource: 4
  m_UserSelectedRegistryName: Keijiro
  m_UserAddingNewScopedRegistry: 0
  m_RegistryInfoDraft:
    m_Modified: 0
    m_ErrorMessage:
    m_UserModificationsInstanceId: -824
    m_OriginalInstanceId: -828
  m_LoadAssets: 0


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!11 &1
AudioManager:
  m_ObjectHideFlags: 0
  serializedVersion: 2
  m_Volume: 1
  Rolloff Scale: 1
  Doppler Factor: 1
  Default Speaker Mode: 2
  m_SampleRate: 0
  m_DSPBufferSize: 1024
  m_VirtualVoiceCount: 512
  m_RealVoiceCount: 32
  m_SpatializerPlugin:
  m_AmbisonicDecoderPlugin:
  m_DisableAudio: 0
  m_VirtualizeEffects: 1
  m_RequestedDSPBufferSize: 1024


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!47 &1
QualitySettings:
  m_ObjectHideFlags: 0
  serializedVersion: 5
  m_CurrentQuality: 0
  m_QualitySettings:
  - serializedVersion: 2
    name: Medium
    pixelLightCount: 1
    shadows: 1
    shadowResolution: 0
    shadowProjection: 1
    shadowCascades: 1
    shadowDistance: 20
    shadowNearPlaneOffset: 3
    shadowCascade2Split: 0.33333334
    shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
    shadowmaskMode: 0
    skinWeights: 2
    textureQuality: 0
    anisotropicTextures: 1
    antiAliasing: 0
    softParticles: 0
    softVegetation: 0
    realtimeReflectionProbes: 0
    billboardsFaceCameraPosition: 0
    vSyncCount: 1
    lodBias: 0.7
    maximumLODLevel: 0
    streamingMipmapsActive: 0
    streamingMipmapsAddAllCameras: 1
    streamingMipmapsMemoryBudget: 512
    streamingMipmapsRenderersPerFrame: 512
    streamingMipmapsMaxLevelReduction: 2
    streamingMipmapsMaxFileIORequests: 1024
    particleRaycastBudget: 64
    asyncUploadTimeSlice: 2
    asyncUploadBufferSize: 16
    asyncUploadPersistentBuffer: 1
    resolutionScalingFixedDPIFactor: 1
    customRenderPipeline: {fileID: 0}
    excludedTargetPlatforms: []
  m_PerPlatformDefaultQuality:
    Android: 0
    Lumin: 0
    Nintendo 3DS: 0
    Nintendo Switch: 0
    PS4: 0
    PSP2: 0
    Server: 0
    Stadia: 0
    Standalone: 0
    WebGL: 0
    Windows Store Apps: 0
    XboxOne: 0
    iPhone: 0
    tvOS: 0


text:
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!126 &1
NavMeshProjectSettings:
  m_ObjectHideFlags: 0
  serializedVersion: 2
  areas:
  - name: Walkable
    cost: 1
  - name: Not Walkable
    cost: 1
  - name: Jump
    cost: 2
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  - name:
    cost: 1
  m_LastAgentTypeID: -887442657
  m_Settings:
  - serializedVersion: 2
    agentTypeID: 0
    agentRadius: 0.5
    agentHeight: 2
    agentSlope: 45
    agentClimb: 0.75
    ledgeDropHeight: 0
    maxJumpAcrossDistance: 0
    minRegionArea: 2
    manualCellSize: 0
    cellSize: 0.16666667
    manualTileSize: 0
    tileSize: 256
    accuratePlacement: 0
    debug:
      m_Flags: 0
  m_SettingNames:
  - Humanoid