Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 116 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 4 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@ categories = ["web-programming::http-server", "multimedia::video"]

[dependencies]
anyhow = "1.0"
async-trait = "0.1"
axum = { version = "0.8", features = ["macros"] }
dashmap = "6.1.0"
dotenvy = "0.15"
governor = "0.10"
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "socks"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "socks"] }
thiserror = "2.0"
tokio = { version = "1", features = ["full"] }
tokio-stream = "0.1"
tower = "0.5"
tower-http = { version = "0.6", features = ["cors", "trace", "compression-full", "fs"] }
tower_governor = "0.8"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
validator = { version = "0.20", features = ["derive"] }
url = "2.5.8"
thiserror = "2.0"
validator = { version = "0.20", features = ["derive"] }

[dev-dependencies]
http-body-util = "0.1"
wiremock = "0.6.5"

[lints.rust]
unsafe_code = "deny"
Expand All @@ -45,12 +45,10 @@ all = { level = "warn", priority = -1 }
pedantic = { level = "warn", priority = -1 }
nursery = { level = "warn", priority = -1 }
cargo = { level = "warn", priority = -1 }
# Allow these to reduce noise for a prototype
multiple_crate_versions = "allow"
missing_errors_doc = "allow"
missing_panics_doc = "allow"
must_use_candidate = "allow"
# Critical ones to keep
unwrap_used = "warn"
expect_used = "warn"
todo = "warn"
Expand Down
1 change: 1 addition & 0 deletions infra/common/cloud-init.template
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ write_files:
ALLOWED_ORIGINS=${ALLOWED_ORIGINS}
WARP_LICENSE_KEY=${WARP_LICENSE_KEY}
MASTER_API_KEY=${MASTER_API_KEY}
GITHUB_PAT=${GHCR_PAT}
Comment thread
nxdun marked this conversation as resolved.

- path: /root/.ghcr_token
permissions: '0600'
Expand Down
1 change: 1 addition & 0 deletions infra/digitalocean/accounts/naduns-team/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ variable "HOST_PORT" {
// - - - - - - - - - - - - - -
variable "GHCR_PAT" {
//SECRET: Expected to be set via root TF_VAR_GHCR_PAT. never Declare
//update: I use this to process contribtion grapth in backend server. to avoid confusion it passed to backend as GITHUB_PAT. im using the same
description = "GitHub Personal Access Token for GHCR login"
Comment thread
nxdun marked this conversation as resolved.
type = string
sensitive = true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
$kind: http-request
name: Contributions (Default User)
url: "{{base_url}}/api/v1/contributions"
method: GET
scripts:
- type: afterResponse
code: >-
pm.test("Status is 200", function () {
pm.response.to.have.status(200);
});

pm.test("Response matches expected schema", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.username).to.be.a('string');
pm.expect(jsonData.meta.provider).to.eql('github');
pm.expect(jsonData.meta.schemaVersion).to.eql(1);
pm.expect(jsonData.cells).to.be.an('array');
pm.expect(jsonData.months).to.be.an('array');
pm.expect(jsonData.summary).to.have.property('totalWeeks');
});
language: text/javascript
order: 3000
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
$kind: http-request
name: Contributions (Specific User)
url: "{{base_url}}/api/v1/contributions?username=nxdun"
method: GET
scripts:
- type: afterResponse
code: >-
pm.test("Status is 200", function () {
pm.response.to.have.status(200);
});

pm.test("Response matches expected schema and specific user", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.username).to.eql('nxdun');
pm.expect(jsonData.meta.provider).to.eql('github');
pm.expect(jsonData.meta.schemaVersion).to.eql(1);
pm.expect(jsonData.cells).to.be.an('array');
pm.expect(jsonData.months).to.be.an('array');
pm.expect(jsonData.summary).to.have.property('totalWeeks');
});
language: text/javascript
order: 3001
13 changes: 13 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,24 @@ pub async fn run() {
let rate_limiters = Arc::new(RateLimiters::new());
log_rate_limit_mode(&config);
let http_client = reqwest::Client::new();

let contributions_service =
Arc::new(crate::services::contributions::ContributionsService::new(
http_client.clone(),
config.github_pat.clone().unwrap_or_default(),
config
.github_username
.clone()
.unwrap_or_else(|| "nxdun".to_string()),
config.github_graphql_url.clone(),
));
Comment thread
nxdun marked this conversation as resolved.

let state = AppState {
config: config.clone(),
ytdlp_manager,
rate_limiters,
http_client,
contributions_service,
};

// 5. Build middleware layers (compression + CORS)
Expand Down
6 changes: 6 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ pub struct AppConfig {
pub max_concurrent_downloads: usize,
pub captcha_secret_key: Option<String>,
pub master_api_key: String,
pub github_pat: Option<String>,
pub github_username: Option<String>,
pub github_graphql_url: String,
}

impl AppConfig {
Expand All @@ -59,6 +62,9 @@ impl AppConfig {
tracing::error!("MASTER_API_KEY must be set to a non-empty value");
std::process::exit(1)
}),
github_pat: env_opt("GITHUB_PAT"),
github_username: env_opt("GITHUB_USERNAME"),
github_graphql_url: env_or("GITHUB_GRAPHQL_URL", "https://api.github.com/graphql"),
}
}

Expand Down
39 changes: 39 additions & 0 deletions src/controllers/api/v1/contributions_controller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use axum::{
Json,
extract::{Query, State},
};
use serde::Deserialize;

use crate::{error::AppError, models::contributions_model::ContributionsResponse, state::AppState};

#[derive(Debug, Deserialize)]
pub struct ContributionsQuery {
pub username: Option<String>,
}

pub async fn get_contributions(
State(state): State<AppState>,
Query(query): Query<ContributionsQuery>,
) -> Result<Json<ContributionsResponse>, AppError> {
let username = query
.username
.as_deref()
.map(str::trim)
.filter(|u| !u.is_empty())
.map_or_else(
|| {
state
.contributions_service
.get_default_username()
.to_string()
},
ToOwned::to_owned,
);

let resp = state
.contributions_service
.get_contributions(&username)
.await?;

Ok(Json(resp))
}
1 change: 1 addition & 0 deletions src/controllers/api/v1/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod contributions_controller;
pub mod ytdlp_controller;
Loading
Loading