mirror of
https://github.com/SrIzan10/ft_cli.git
synced 2026-06-06 00:56:54 +00:00
week one (project fetching
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/target
|
||||
.env
|
||||
1741
Cargo.lock
generated
Normal file
1741
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "ft_cli"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
dotenv = "0.15.0"
|
||||
reqwest = { version = "0.12", features = ["json", "blocking"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
942
ft-api.json
Normal file
942
ft-api.json
Normal file
@@ -0,0 +1,942 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"info": {
|
||||
"title": "Flavortown API",
|
||||
"version": "v1",
|
||||
"description": "You need an API key to use this! Go to your [account settings](https://flavortown.hackclub.com/kitchen?settings=1) to get one."
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://flavortown.hackclub.com/api/v1"
|
||||
}
|
||||
],
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"securitySchemes": {
|
||||
"bearerAuth": {
|
||||
"type": "http",
|
||||
"scheme": "bearer",
|
||||
"description": "Include your API key via `Authorization: Bearer YOUR_API_KEY`. You can find or regenerate your API key in your [account settings](https://flavortown.hackclub.com/kitchen?settings=1)."
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"Pagination": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"current_page": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total_pages": {
|
||||
"type": "integer"
|
||||
},
|
||||
"total_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"next_page": {
|
||||
"type": "integer",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"Project": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"repo_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"demo_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"readme_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"ai_declaration": {
|
||||
"type": "string"
|
||||
},
|
||||
"ship_status": {
|
||||
"type": "string"
|
||||
},
|
||||
"devlog_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"banner_url": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Comment": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"author": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"avatar": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"body": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Devlog": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"body": {
|
||||
"type": "string"
|
||||
},
|
||||
"comments_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"duration_seconds": {
|
||||
"type": "integer"
|
||||
},
|
||||
"likes_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"scrapbook_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"created_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"media": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"content_type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Comment"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"User": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"slack_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"avatar": {
|
||||
"type": "string"
|
||||
},
|
||||
"project_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"cookies": {
|
||||
"type": "integer",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"UserDetail": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/User"
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vote_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"like_count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"devlog_seconds_total": {
|
||||
"type": "integer"
|
||||
},
|
||||
"devlog_seconds_today": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"RegionEnabled": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled_au": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enabled_ca": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enabled_eu": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enabled_in": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enabled_uk": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enabled_us": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enabled_xx": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"TicketCost": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"base_cost": {
|
||||
"type": "number"
|
||||
},
|
||||
"au": {
|
||||
"type": "number"
|
||||
},
|
||||
"ca": {
|
||||
"type": "number"
|
||||
},
|
||||
"eu": {
|
||||
"type": "number"
|
||||
},
|
||||
"in": {
|
||||
"type": "number"
|
||||
},
|
||||
"uk": {
|
||||
"type": "number"
|
||||
},
|
||||
"us": {
|
||||
"type": "number"
|
||||
},
|
||||
"xx": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StoreItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"old_prices": {
|
||||
"type": "array",
|
||||
"items": {}
|
||||
},
|
||||
"limited": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"stock": {
|
||||
"type": "integer"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"show_in_carousel": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"accessory_tag": {
|
||||
"type": "string"
|
||||
},
|
||||
"agh_contents": {
|
||||
"type": "string"
|
||||
},
|
||||
"attached_shop_item_ids": {
|
||||
"type": "array",
|
||||
"items": {}
|
||||
},
|
||||
"buyable_by_self": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"long_description": {
|
||||
"type": "string"
|
||||
},
|
||||
"max_qty": {
|
||||
"type": "integer"
|
||||
},
|
||||
"one_per_person_ever": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sale_percentage": {
|
||||
"type": "integer"
|
||||
},
|
||||
"image_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "#/components/schemas/RegionEnabled"
|
||||
},
|
||||
"ticket_cost": {
|
||||
"$ref": "#/components/schemas/TicketCost"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Error": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ValidationErrors": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"errors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"Unauthorized": {
|
||||
"description": "Missing or invalid API key",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
},
|
||||
"example": {
|
||||
"error": "Invalid API key"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Forbidden": {
|
||||
"description": "Permission denied",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"NotFound": {
|
||||
"description": "Resource not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
},
|
||||
"example": {
|
||||
"error": "Resource not found"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"UnprocessableEntity": {
|
||||
"description": "Validation failed",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ValidationErrors"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/projects": {
|
||||
"get": {
|
||||
"summary": "List projects",
|
||||
"tags": [
|
||||
"Projects"
|
||||
],
|
||||
"description": "Fetch a list of projects. Ratelimit: 5 reqs/min, 20 reqs/min if searching.",
|
||||
"operationId": "listProjects",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "page",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
},
|
||||
"description": "Page number for pagination"
|
||||
},
|
||||
{
|
||||
"name": "query",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Search projects by title or description"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A paginated list of projects",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"projects": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Project"
|
||||
}
|
||||
},
|
||||
"pagination": {
|
||||
"$ref": "#/components/schemas/Pagination"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"summary": "Create a project",
|
||||
"tags": [
|
||||
"Projects"
|
||||
],
|
||||
"description": "Create a new project.",
|
||||
"operationId": "createProject",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Project created",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"422": {
|
||||
"$ref": "#/components/responses/UnprocessableEntity"
|
||||
}
|
||||
},
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"title",
|
||||
"description"
|
||||
],
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Project title"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Project description"
|
||||
},
|
||||
"repo_url": {
|
||||
"type": "string",
|
||||
"description": "URL to the source code repository"
|
||||
},
|
||||
"demo_url": {
|
||||
"type": "string",
|
||||
"description": "URL to the live demo"
|
||||
},
|
||||
"readme_url": {
|
||||
"type": "string",
|
||||
"description": "URL to the README"
|
||||
},
|
||||
"ai_declaration": {
|
||||
"type": "string",
|
||||
"description": "Declaration of AI tools used in this project"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/projects/{id}": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"summary": "Get a project",
|
||||
"tags": [
|
||||
"Projects"
|
||||
],
|
||||
"description": "Fetch a specific project by ID. Ratelimit: 30 reqs/min.",
|
||||
"operationId": "getProject",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A single project",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/NotFound"
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"summary": "Update a project",
|
||||
"tags": [
|
||||
"Projects"
|
||||
],
|
||||
"description": "Update an existing project.",
|
||||
"operationId": "updateProject",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Project updated",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/Forbidden"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/NotFound"
|
||||
},
|
||||
"422": {
|
||||
"$ref": "#/components/responses/UnprocessableEntity"
|
||||
}
|
||||
},
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "Project title"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Project description"
|
||||
},
|
||||
"repo_url": {
|
||||
"type": "string",
|
||||
"description": "URL to the source code repository"
|
||||
},
|
||||
"demo_url": {
|
||||
"type": "string",
|
||||
"description": "URL to the live demo"
|
||||
},
|
||||
"readme_url": {
|
||||
"type": "string",
|
||||
"description": "URL to the README"
|
||||
},
|
||||
"ai_declaration": {
|
||||
"type": "string",
|
||||
"description": "Declaration of AI tools used in this project"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"/projects/{project_id}/devlogs": {
|
||||
"get": {
|
||||
"summary": "List project devlogs",
|
||||
"tags": [
|
||||
"Projects"
|
||||
],
|
||||
"description": "Fetch all devlogs for a specific project.",
|
||||
"operationId": "listProjectDevlogs",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "project_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A paginated list of devlogs for the project",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"devlogs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Devlog"
|
||||
}
|
||||
},
|
||||
"pagination": {
|
||||
"$ref": "#/components/schemas/Pagination"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/NotFound"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/devlogs": {
|
||||
"get": {
|
||||
"summary": "List devlogs",
|
||||
"tags": [
|
||||
"Devlogs"
|
||||
],
|
||||
"description": "Fetch all devlogs across all projects.",
|
||||
"operationId": "listDevlogs",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "page",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
},
|
||||
"description": "Page number for pagination"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A paginated list of devlogs",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"devlogs": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Devlog"
|
||||
}
|
||||
},
|
||||
"pagination": {
|
||||
"$ref": "#/components/schemas/Pagination"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/devlogs/{id}": {
|
||||
"get": {
|
||||
"summary": "Get a devlog",
|
||||
"tags": [
|
||||
"Devlogs"
|
||||
],
|
||||
"description": "Fetch a devlog by ID.",
|
||||
"operationId": "getDevlog",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A single devlog",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Devlog"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/NotFound"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/store": {
|
||||
"get": {
|
||||
"summary": "List store items",
|
||||
"tags": [
|
||||
"Store"
|
||||
],
|
||||
"description": "Fetch a list of store items. Ratelimit: 5 reqs/min.",
|
||||
"operationId": "listStoreItems",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A list of store items",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/StoreItem"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/store/{id}": {
|
||||
"get": {
|
||||
"summary": "Get a store item",
|
||||
"tags": [
|
||||
"Store"
|
||||
],
|
||||
"description": "Fetch a specific store item by ID. Ratelimit: 30 reqs/min.",
|
||||
"operationId": "getStoreItem",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A single store item",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/StoreItem"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/NotFound"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users": {
|
||||
"get": {
|
||||
"summary": "List users",
|
||||
"tags": [
|
||||
"Users"
|
||||
],
|
||||
"description": "Fetch a list of users. Ratelimit: 5 reqs/min.",
|
||||
"operationId": "listUsers",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "page",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
},
|
||||
"description": "Page number for pagination"
|
||||
},
|
||||
{
|
||||
"name": "query",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Search users by display name or slack ID"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A paginated list of users",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"users": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/User"
|
||||
}
|
||||
},
|
||||
"pagination": {
|
||||
"$ref": "#/components/schemas/Pagination"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/users/{id}": {
|
||||
"get": {
|
||||
"summary": "Get a user",
|
||||
"tags": [
|
||||
"Users"
|
||||
],
|
||||
"description": "Fetch a specific user by ID. Use \"me\" as the ID to fetch the authenticated user.",
|
||||
"operationId": "getUser",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "User ID or \"me\" for the authenticated user"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A single user with additional stats",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UserDetail"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/NotFound"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
src/main.rs
Normal file
79
src/main.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use dotenv::dotenv;
|
||||
use std::env;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct User {
|
||||
pub id: u64,
|
||||
pub slack_id: String,
|
||||
pub display_name: String,
|
||||
pub avatar: String,
|
||||
pub project_ids: Vec<u64>,
|
||||
pub cookies: Option<u64>,
|
||||
pub vote_count: u64,
|
||||
pub like_count: u64,
|
||||
pub devlog_seconds_total: u64,
|
||||
pub devlog_seconds_today: u64,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Project {
|
||||
pub id: u64,
|
||||
pub title: String,
|
||||
pub description: String,
|
||||
pub repo_url: String,
|
||||
pub demo_url: String,
|
||||
pub readme_url: String,
|
||||
pub ai_declaration: Option<String>,
|
||||
pub ship_status: String,
|
||||
pub devlog_ids: Vec<u64>,
|
||||
pub banner_url: Option<String>,
|
||||
pub created_at: String,
|
||||
pub updated_at: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
dotenv().ok();
|
||||
|
||||
let ft_key = env::var("FT_KEY").expect("FT_KEY must be set");
|
||||
let client = reqwest::blocking::Client::new();
|
||||
|
||||
let user: User = client
|
||||
.get("https://flavortown.hackclub.com/api/v1/users/me")
|
||||
.header("Authorization", format!("Bearer {}", ft_key))
|
||||
.send()
|
||||
.expect("Failed to send request")
|
||||
.json()
|
||||
.expect("Failed to parse JSON");
|
||||
|
||||
let mut projects: Vec<Project> = Vec::new();
|
||||
|
||||
println!("Logged in as {}", user.display_name);
|
||||
let cookies_display = user
|
||||
.cookies
|
||||
.map_or("(undeclared)".to_string(), |count| count.to_string());
|
||||
println!(
|
||||
"You have {} cookies and have voted {} times.",
|
||||
cookies_display, user.vote_count
|
||||
);
|
||||
for pid in user.project_ids {
|
||||
let project: Project = client
|
||||
.get(format!("https://flavortown.hackclub.com/api/v1/projects/{}", pid))
|
||||
.header("Authorization", format!("Bearer {}", ft_key))
|
||||
.send()
|
||||
.expect("Failed to send request")
|
||||
.json()
|
||||
.expect("Failed to parse JSON");
|
||||
projects.push(project);
|
||||
}
|
||||
|
||||
println!(
|
||||
"Your projects are: {}",
|
||||
projects
|
||||
.iter()
|
||||
.map(|p| p.title.as_str())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user