Skip to content

Commit

Permalink
Github pins, spotify recents, bug fixes (#3)
Browse files Browse the repository at this point in the history
* Remove ls from dockerfile
Fix issue with spotify history repeat inserting

* spotify: Add recent listens route with limit param
github: Add github route for pinned repos
spotify: Stop from querying db every second, *clueless*
  • Loading branch information
dustinrouillard authored May 24, 2024
1 parent 5dfefae commit ffbfe69
Show file tree
Hide file tree
Showing 17 changed files with 238 additions and 22 deletions.
13 changes: 13 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ bytes = "1.6.0"
once_cell = "1.19.0"
sha1 = "0.10.6"
hex = "0.4.3"
gql_client = "1.0.7"

[profile.release]
lto = true
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ There is probably a lot of better ways to do many of the things I've done here,

- Spotify History and Now Playing API / Queue Messages
- File and Screenshot Uploads
- Github pinned repositories
- Blog System for Personal Site
2 changes: 1 addition & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
generator client {
provider = "cargo prisma"
output = "../src/connectivity/prisma.rs"
module_path = "crate::connectivity::prisma"
module_path = "connectivity::prisma"
}

datasource db {
Expand Down
3 changes: 3 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,7 @@ pub struct Config {

#[envconfig(from = "S3_FILES_ALIAS", default = "files.dstn.to")]
pub s3_files_alias: String,

#[envconfig(from = "GITHUB_PAT", default = "")]
pub github_pat: String,
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
.service(services::base::health)
.service(services::uploads::factory::uploads_factory())
.service(services::spotify::factory::spotify_factory())
.service(services::github::factory::github_factory())
.service(services::blog::factory::blog_factory()),
)
})
Expand Down
24 changes: 6 additions & 18 deletions src/modules/spotify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ pub(crate) async fn fetch_spotify_current(data: web::Data<ServerState>) {
Utc::now().with_timezone(&FixedOffset::east_opt(0).unwrap());
let current_playing = Arc::clone(&current_clone);

if current_playing.progress.unwrap() < 10000 {
return;
}

match prisma
.spotify_history()
.find_first(vec![spotify_history::id::equals(
Expand All @@ -118,29 +122,13 @@ pub(crate) async fn fetch_spotify_current(data: web::Data<ServerState>) {
let date_minus_length =
(date.timestamp() * 1000) - latest.length as i64;

if current_playing.progress.unwrap() < 10000 {
return;
}

if date_minus_length >= listened_date {
store_history(prisma, current_playing).await;
}
}
None => {
if current_playing.progress.unwrap() < 10000 {
return;
}

store_history(prisma, current_playing).await;
}
None => store_history(prisma, current_playing).await,
},
Err(_) => {
if current_playing.progress.unwrap() < 10000 {
return;
}

store_history(prisma, current_playing).await;
}
Err(_) => store_history(prisma, current_playing).await,
}
}
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/services/blog/posts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async fn get_posts(
.find_many(vec![blog_posts::visibility::equals("public".to_string())])
.take(query.limit.unwrap_or(25))
.skip(query.offset.unwrap_or(0))
.order_by(blog_posts::published_at::order(Direction::Asc))
.order_by(blog_posts::published_at::order(Direction::Desc))
.exec()
.await;

Expand Down Expand Up @@ -81,7 +81,7 @@ async fn get_all_posts(
.find_many(vec![])
.take(query.limit.unwrap_or(25))
.skip(query.offset.unwrap_or(0))
.order_by(blog_posts::created_at::order(Direction::Asc))
.order_by(blog_posts::created_at::order(Direction::Desc))
.exec()
.await;

Expand Down
7 changes: 7 additions & 0 deletions src/services/github/factory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use actix_web::{web, Scope};

use crate::services;

pub fn github_factory() -> Scope {
web::scope("/github").service(services::github::routes::github_pinned)
}
2 changes: 2 additions & 0 deletions src/services/github/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod factory;
pub mod routes;
99 changes: 99 additions & 0 deletions src/services/github/routes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use std::collections::HashMap;

use actix_web::{get, http::Error, web, HttpResponse};
use envconfig::Envconfig;
use gql_client::Client;
use redis::{aio::ConnectionManager, AsyncCommands, RedisError};
use serde_json::json;

use crate::{config::Config, structs::github::Data, ServerState};

#[get("/pinned")]
async fn github_pinned(
state: web::Data<ServerState>,
) -> Result<HttpResponse, Error> {
let query = "
query GithubUserPins {
user(login: \"dustinrouillard\") {
pinnedItems(first: 6, types: [REPOSITORY]) {
totalCount
edges {
node {
... on Repository {
owner {
login
}
name
description
stargazerCount
forkCount
primaryLanguage {
name
color
}
pushedAt
url
}
}
}
}
}
}
";

let valkey = &mut state.valkey.clone();

let cached = redis::cmd("GET")
.arg("cache/github/pinned")
.query_async::<ConnectionManager, String>(&mut valkey.cm)
.await;

let response: Vec<serde_json::Value> = if let Err(_) = cached {
let config = Config::init_from_env().unwrap();

let mut headers = HashMap::new();
headers.insert("user-agent", "rest.dstn.to/2.0".to_string());
headers
.insert("authorization", format!("token {}", config.github_pat));

let client =
Client::new_with_headers("https://api.github.com/graphql", headers);

let data = client.query::<Data>(query).await.unwrap();

let response = data
.unwrap()
.user
.pinned_items
.edges
.iter()
.map(|edge| {
json!({
"owner": edge.node.owner.login,
"name": edge.node.name,
"description": edge.node.description,
"stars": edge.node.stargazer_count,
"forks": edge.node.fork_count,
"language": edge.node.primary_language,
"pushed_at": edge.node.pushed_at,
"url": edge.node.url,
})
})
.collect();

let _: Result<String, RedisError> = valkey
.cm
.set_ex("cache/github/pinned", json!(response).to_string(), 1800)
.await;

response
} else {
serde_json::from_str(&cached.unwrap()).unwrap()
};

Ok(
HttpResponse::Ok()
.insert_header(("Content-Type", "application/json"))
.body(json!({"repositories": response}).to_string()),
)
}
1 change: 1 addition & 0 deletions src/services/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod base;
pub mod blog;
pub mod github;
pub mod spotify;
pub mod uploads;
1 change: 1 addition & 0 deletions src/services/spotify/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::services;

pub fn spotify_factory() -> Scope {
web::scope("/spotify")
.service(services::spotify::routes::recent_listens)
.service(services::spotify::routes::current)
.service(services::spotify::routes::authorize)
.service(services::spotify::routes::setup)
Expand Down
47 changes: 46 additions & 1 deletion src/services/spotify/routes.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use actix_web::{get, http::Error, web, HttpResponse};
use envconfig::Envconfig;
use prisma_client_rust::Direction;
use redis::{aio::ConnectionManager, AsyncCommands};
use serde::{Deserialize, Serialize};
use serde_json::json;

use crate::{
config::Config,
connectivity::prisma::spotify_history,
services::spotify::helpers,
structs::spotify::{AuthorizationData, SpotifyTokens},
structs::spotify::{AuthorizationData, RecentSongQuery, SpotifyTokens},
ServerState,
};

Expand Down Expand Up @@ -36,6 +38,49 @@ async fn current(
)
}

#[get("/recents")]
async fn recent_listens(
state: web::Data<ServerState>,
query: Option<web::Query<RecentSongQuery>>,
) -> Result<HttpResponse, Error> {
let prisma = &mut &state.prisma;

let query: web::Query<RecentSongQuery> = query
.unwrap_or(actix_web::web::Query(RecentSongQuery { limit: Some(10) }));

let recents = prisma
.spotify_history()
.find_many(vec![])
.order_by(spotify_history::listened_at::order(Direction::Desc))
.take(query.limit.unwrap_or(10))
.include(spotify_history::include!({ spotify_devices: select { id name r#type } }))
.exec()
.await;

let recents: Vec<serde_json::Value> = recents
.unwrap()
.into_iter()
.map(|recent| {
json!({
"id": recent.id,
"type": recent.r#type,
"name": recent.name,
"artists": recent.artists,
"length": recent.length,
"image": recent.image,
"device": recent.spotify_devices,
"listened_at": recent.listened_at
})
})
.collect();

Ok(
HttpResponse::Ok()
.insert_header(("Content-Type", "application/json"))
.body(json!({"recents": recents}).to_string()),
)
}

#[get("/authorize")]
async fn authorize(
data: web::Data<ServerState>,
Expand Down
48 changes: 48 additions & 0 deletions src/structs/github.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
pub struct Data {
pub user: User,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct User {
pub pinned_items: PinnedItems,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct PinnedItems {
pub total_count: i64,
pub edges: Vec<Edge>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Edge {
pub node: Node,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Node {
pub owner: Owner,
pub name: String,
pub description: String,
pub stargazer_count: i64,
pub fork_count: i64,
pub primary_language: Option<PrimaryLanguage>,
pub pushed_at: String,
pub url: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Owner {
pub login: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct PrimaryLanguage {
pub name: String,
pub color: String,
}
1 change: 1 addition & 0 deletions src/structs/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod blog;
pub mod github;
pub mod spotify;
pub mod uploads;
5 changes: 5 additions & 0 deletions src/structs/spotify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
extern crate serde_json;

#[derive(Deserialize, Debug)]
pub struct RecentSongQuery {
pub limit: Option<i64>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PlayerState {
pub device: Device,
Expand Down

0 comments on commit ffbfe69

Please sign in to comment.