Skip to content

Commit 7db6f8c

Browse files
committed
2.0.0
1 parent 1c009fd commit 7db6f8c

File tree

8 files changed

+44
-41
lines changed

8 files changed

+44
-41
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "query_api"
3-
version = "1.8.0"
3+
version = "2.0.0"
44
edition = "2021"
55

66
[dependencies]

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<img alt="license" src="https://img.shields.io/discord/796790757947867156?color=4166f5&label=discord&style=flat-square" />
1010
</a>
1111

12-
A versatile API facade for the Hypixel Auction API written in Rust. The entire auction house is fetched with NBT parsing and inserted into a PostgreSQL database in about 3-7 seconds every minute with low memory usage (can vary depending on enabled features, network speed, and latency of the Hypixel API)! You can query by auction UUID, auctioneer, end time, item name, item tier, item id, price, enchants, bin and bids. You can sort by the item's bin / starting price. You can track the average price of each unique pet-level-rarity combination. You can track the lowest prices of all bins. It also can track new bins that are at least one million lower than previous bins. Lastly, it can track the average auction prices and sales up to five days with custom 'averaging methods'.
12+
A versatile API facade for the Hypixel Auction API written in Rust. The entire auction house is fetched with NBT parsing and inserted into a PostgreSQL database in about 2-5 seconds every minute with low memory usage (varies depending on enabled features, network speed, hardware, and latency of the Hypixel API)! You can query by auction UUID, auctioneer, end time, item name, item tier, item id, price, enchants, bin and bids. You can sort by the item's bin / starting price. You can track the average price of each unique pet-level-rarity combination. You can track the lowest prices of all bins. It also can track new bins that are at least one million lower than previous bins. Lastly, it can track the average auction prices and sales up to five days with custom 'averaging methods'.
1313

1414
## Set Up
1515
### Prerequisites
@@ -20,19 +20,19 @@ A versatile API facade for the Hypixel Auction API written in Rust. The entire a
2020

2121
### Steps
2222
- Clone the repository
23-
- Rename the `.example_env` file to `.env` and fill out all fields **OR** set all fields using environment variables
24-
- Run `cargo run --release` (may take some time to build)
23+
- Rename the `.example_env` file to `.env` and fill out required fields **OR** set required fields using environment variables
24+
- Run `cargo run --release` (may take time to build)
2525
- Use it!
2626

2727
### Configuration Fields or Environment Variables
28-
- `BASE_URL`: The base URL of the domain such as 127.0.0.1
29-
- `PORT`: The port such as 8080
30-
- `API_KEY`: Key needed to access this API (NOT a Hypixel API key)
31-
- `ADMIN_API_KEY`: Admin key required to use raw SQL parameters. Will default to the API_KEY if not provided
32-
- `POSTGRES_URL`: Full URL of a PostgreSQL database
33-
- `WEBHOOK_URL`: Discord webhook URL for logging
34-
- `FEATURES`: The features (QUERY, PETS, LOWESTBIN, UNDERBIN, AVERAGE_AUCTION, AVERAGE_BIN) you want to be enabled separated with a '+'
35-
- `DEBUG`: If the API should log to files and stdout (true or false)
28+
- `BASE_URL`: Base address of the host (e.g. 0.0.0.0)
29+
- `PORT`: The port such (e.g. 8000)
30+
- `API_KEY`: Optional key needed to access this API (NOT a Hypixel API key)
31+
- `ADMIN_API_KEY`: Optional admin key required to use raw SQL parameters (defaults to the API_KEY)
32+
- `POSTGRES_URL`: Full URL of a PostgreSQL database (should look like `postgres://[user]:[password]@[host]:[port]/[dbname]`)
33+
- `WEBHOOK_URL`: Optional Discord webhook URL for logging
34+
- `FEATURES`: Features (QUERY, PETS, LOWESTBIN, UNDERBIN, AVERAGE_AUCTION, AVERAGE_BIN) you want to enabled separated with a '+'
35+
- `DEBUG`: If the API should log to files and stdout (defaults to false)
3636

3737
## Usage
3838
### Endpoints
@@ -51,7 +51,7 @@ A versatile API facade for the Hypixel Auction API written in Rust. The entire a
5151
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
5252

5353
### Free PostgreSQL Datbase
54-
For a free PostgreSQL database host, [Supabase](https://supabase.com/) is a really good choice and offers two free databases with plenty of space and performance.
54+
For a free cloud PostgreSQL database, the free tier of [Supabase](https://supabase.com/) is a really good choice with with plenty of storage and performance.
5555

5656
### Deploy To Railway
5757
[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/new/template?template=https://github.com/kr45732/rust-query-api&plugins=postgresql&envs=BASE_URL,API_KEY,ADMIN_API_KEY,POSTGRES_URL,WEBHOOK_URL,FEATURES&optionalEnvs=WEBHOOK_URL,ADMIN_API_KEY&BASE_URLDesc=The+base+URL+of+the+domain.+Do+not+modify+this&API_KEYDesc=Key+needed+to+access+this+API+(NOT+a+Hypixel+API+key)&ADMIN_API_KEYDesc=Admin+key+required+to+use+raw+SQL+parameters.+Will+default+to+the+API_KEY+if+not+provided&POSTGRES_URLDesc=Full+URL+of+a+PostgreSQL+database.+No+need+to+modify+this+unless+you+are+using+your+own+database+since+Railway+already+provides+this+for+you.&WEBHOOK_URLDesc=Discord+webhook+URL+for+logging&FEATURESDesc=The+features+(QUERY,+PETS,+LOWESTBIN,+UNDERBIN,+AVERAGE_AUCTION,+AVERAGE_BIN)+you+want+enabled+separated+with+commas&BASE_URLDefault=0.0.0.0&POSTGRES_URLDefault=$%7B%7BDATABASE_URL%7D%7D&FEATURESDefault=QUERY,LOWESTBIN,AVERAGE_AUCTION,AVERAGE_BIN&referralCode=WrEybV)

src/api_handler.rs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ pub async fn update_auctions(config: Arc<Config>) {
156156
.await;
157157
}
158158

159-
let fetch_sec = started.elapsed().as_secs();
160-
info!("Total fetch time: {}s", started.elapsed().as_secs());
159+
let fetch_sec = started.elapsed().as_secs_f32();
160+
info!("Total fetch time: {:.2}s", fetch_sec);
161161

162162
debug!("Inserting into database");
163163
let insert_started = Instant::now();
@@ -190,7 +190,7 @@ pub async fn update_auctions(config: Arc<Config>) {
190190

191191
if update_query {
192192
let query_started = Instant::now();
193-
update_query_items_local(query_prices.iter().map(|o| o.item_name.clone()).collect()).await;
193+
update_query_items_local(query_prices.iter().map(|o| o.item_name.as_str()).collect()).await;
194194
let _ = match update_query_database(query_prices).await {
195195
Ok(rows) => write!(
196196
ok_logs,
@@ -256,11 +256,11 @@ pub async fn update_auctions(config: Arc<Config>) {
256256
}
257257

258258
info(format!(
259-
"Fetch time: {}s ({} failed) | Insert time: {}s | Total time: {}s",
259+
"Fetch time: {:.2}s ({} failed) | Insert time: {:.2}s | Total time: {:.2}s",
260260
fetch_sec,
261261
num_failed,
262-
insert_started.elapsed().as_secs(),
263-
started.elapsed().as_secs()
262+
insert_started.elapsed().as_secs_f32(),
263+
started.elapsed().as_secs_f32()
264264
));
265265

266266
*IS_UPDATING.lock().await = false;
@@ -283,8 +283,7 @@ fn parse_auctions(
283283
for auction in auctions {
284284
// Prevent duplicate auctions (returns false if already exists)
285285
if inserted_uuids.insert(auction.uuid.to_string()) {
286-
let mut tier = auction.tier.as_str();
287-
let pet_info;
286+
let mut tier = auction.tier;
288287

289288
let nbt = &parse_nbt(&auction.item_bytes).unwrap().i[0];
290289
let item_id = nbt.tag.extra_attributes.id.to_owned();
@@ -301,17 +300,17 @@ fn parse_auctions(
301300
bin_prices,
302301
);
303302
}
303+
304304
if update_query {
305305
enchants.push(format!("{};{}", entry.key().to_uppercase(), entry.value()));
306306
}
307307
}
308308
} else if item_id == "PET" {
309-
pet_info =
310-
serde_json::from_str::<Value>(nbt.tag.extra_attributes.pet.as_ref().unwrap())
311-
.unwrap();
312-
313309
// If the pet is tier boosted, the tier field in the auction shows the rarity after boosting
314-
tier = pet_info.get("tier").unwrap().as_str().unwrap();
310+
tier =
311+
serde_json::from_str::<PetInfo>(nbt.tag.extra_attributes.pet.as_ref().unwrap())
312+
.unwrap()
313+
.tier;
315314

316315
if auction.bin && update_lowestbin {
317316
let mut split = auction.item_name.split("] ");
@@ -321,7 +320,7 @@ fn parse_auctions(
321320
internal_id = format!(
322321
"{};{}",
323322
pet_name.replace(' ', "_").replace("_✦", "").to_uppercase(),
324-
match tier {
323+
match tier.as_str() {
325324
"COMMON" => 0,
326325
"UNCOMMON" => 1,
327326
"RARE" => 2,
@@ -440,7 +439,7 @@ async fn parse_ended_auctions(
440439
_ => continue,
441440
}
442441
} else if id == "PET" {
443-
let pet_info = serde_json::from_str::<Value>(
442+
let pet_info = serde_json::from_str::<PetInfo>(
444443
nbt.tag.extra_attributes.pet.as_ref().unwrap(),
445444
)
446445
.unwrap();
@@ -453,11 +452,9 @@ async fn parse_ended_auctions(
453452
let pet_id = format!(
454453
"{}_{}{}",
455454
item_name.replace(' ', "_").replace("_✦", ""),
456-
pet_info.get("tier").unwrap().as_str().unwrap(),
457-
if let Some(held_item) =
458-
pet_info.get("heldItem").and_then(|v| v.as_str())
459-
{
460-
match held_item {
455+
pet_info.tier,
456+
if let Some(held_item) = pet_info.held_item {
457+
match held_item.as_str() {
461458
"PET_ITEM_TIER_BOOST"
462459
| "PET_ITEM_VAMPIRE_FANG"
463460
| "PET_ITEM_TOY_JERRY" => "_TB",
@@ -493,7 +490,7 @@ async fn parse_ended_auctions(
493490
.replace(' ', "_")
494491
.replace("_✦", "")
495492
.to_uppercase(),
496-
match pet_info.get("tier").unwrap().as_str().unwrap() {
493+
match pet_info.tier.as_str() {
497494
"COMMON" => 0,
498495
"UNCOMMON" => 1,
499496
"RARE" => 2,

src/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl Config {
4848
pub fn load_or_panic() -> Self {
4949
let base_url = get_env("BASE_URL");
5050
let port = get_env("PORT").parse::<u32>().expect("PORT not valid");
51-
let api_key = get_env("API_KEY");
51+
let api_key = env::var("API_KEY").unwrap_or_default();
5252
let webhook_url = env::var("WEBHOOK_URL").unwrap_or_default();
5353
let admin_api_key = env::var("ADMIN_API_KEY").unwrap_or_else(|_| api_key.clone());
5454
let debug = env::var("DEBUG")

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
1818

19-
#![warn(clippy::all, clippy::pedantic)]
19+
#![warn(clippy::all)]
2020

2121
use std::sync::Arc;
2222
use std::{

src/structs.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ pub struct DisplayInfo {
181181
// pub lore: Vec<String>,
182182
}
183183

184+
#[derive(Deserialize)]
185+
pub struct PetInfo {
186+
pub tier: String,
187+
#[serde(rename = "heldItem")]
188+
pub held_item: Option<String>,
189+
}
190+
184191
#[derive(Deserialize)]
185192
pub struct Auctions {
186193
pub page: i64,

src/utils.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,9 @@ pub fn update_lower_else_insert(id: &String, starting_bid: i64, prices: &mut Das
176176
if starting_bid < *ele {
177177
*ele = starting_bid;
178178
}
179-
return;
179+
} else {
180+
prices.insert(id.clone(), starting_bid);
180181
}
181-
182-
prices.insert(id.clone(), starting_bid);
183182
}
184183

185184
pub async fn update_query_database(auctions: Vec<DatabaseItem>) -> Result<u64, Error> {
@@ -350,7 +349,7 @@ pub async fn update_under_bins_local(bin_prices: &Vec<Value>) -> Result<(), serd
350349
serde_json::to_writer(file, bin_prices)
351350
}
352351

353-
pub async fn update_query_items_local(query_items: DashSet<String>) {
352+
pub async fn update_query_items_local(query_items: DashSet<&str>) {
354353
let file = OpenOptions::new()
355354
.create(true)
356355
.write(true)

0 commit comments

Comments
 (0)