diff --git a/torn-api-codegen/src/model/enum.rs b/torn-api-codegen/src/model/enum.rs index 2012181..cac4b40 100644 --- a/torn-api-codegen/src/model/enum.rs +++ b/torn-api-codegen/src/model/enum.rs @@ -8,7 +8,7 @@ use crate::openapi::{ r#type::{OpenApiType, OpenApiVariants}, }; -use super::{object::PrimitiveType, ResolvedSchema}; +use super::{object::PrimitiveType, Model, ResolvedSchema}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum EnumRepr { @@ -143,6 +143,18 @@ impl EnumVariantTupleValue { }, } } + + pub fn is_comparable(&self, resolved: &ResolvedSchema) -> bool { + match self { + Self::Primitive(_) => true, + Self::Enum { inner, .. } => inner.is_comparable(resolved), + Self::Ref { ty_name } | Self::ArrayOfRefs { ty_name } => resolved + .models + .get(ty_name) + .map(|m| matches!(m, Model::Newtype(_))) + .unwrap_or_default(), + } + } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -173,6 +185,13 @@ impl EnumVariantValue { } } + pub fn is_comparable(&self, resolved: &ResolvedSchema) -> bool { + match self { + Self::Repr(_) | Self::String { .. } => true, + Self::Tuple(values) => values.iter().all(|v| v.is_comparable(resolved)), + } + } + pub fn codegen_display(&self, name: &str) -> Option { let variant = format_ident!("{name}"); @@ -417,6 +436,12 @@ impl Enum { self.variants.iter().all(|v| v.value.is_display(resolved)) } + pub fn is_comparable(&self, resolved: &ResolvedSchema) -> bool { + self.variants + .iter() + .all(|v| v.value.is_comparable(resolved)) + } + pub fn codegen(&self, resolved: &ResolvedSchema) -> Option { let repr = self.repr.map(|r| match r { EnumRepr::U8 => quote! { #[repr(u8)]}, @@ -458,7 +483,11 @@ impl Enum { } if self.copy { - derives.push(quote! { Copy, Hash }); + derives.push(quote! { Copy }); + } + + if self.is_comparable(resolved) { + derives.push(quote! { Eq, Hash }); } let serde_attr = self.untagged.then(|| { diff --git a/torn-api-codegen/src/model/parameter.rs b/torn-api-codegen/src/model/parameter.rs index 27ba1c9..a77b663 100644 --- a/torn-api-codegen/src/model/parameter.rs +++ b/torn-api-codegen/src/model/parameter.rs @@ -315,7 +315,7 @@ The default value [Self::{}](self::{}#variant.{})"#, let inner_ty = items.codegen_type_name(&inner_name); code.extend(quote! { - #[derive(Debug, Clone)] + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct #name(pub Vec<#inner_ty>); impl std::fmt::Display for #name { diff --git a/torn-api/openapi.json b/torn-api/openapi.json index e70979a..bee9fe7 100644 --- a/torn-api/openapi.json +++ b/torn-api/openapi.json @@ -3,7 +3,7 @@ "info": { "title": "Torn API", "description": "\n * The development of Torn's API v2 is still ongoing.\n * If selections remain unaltered, they will default to the API v1 version.\n * Unlike API v1, API v2 accepts both selections and IDs as path and query parameters.\n * If any discrepancies or errors are found, please submit a [bug report](https://www.torn.com/forums.php#/p=forums&f=19&b=0&a=0) on the Torn Forums.\n * In case you're using bots to check for changes on openapi.json file, make sure to specificy a custom user-agent header - CloudFlare sometimes prevents requests from default user-agents.", - "version": "1.7.0" + "version": "1.8.0" }, "servers": [ { @@ -1188,12 +1188,7 @@ "description": "Category of races returned", "required": false, "schema": { - "type": "string", - "default": "custom", - "enum": [ - "official", - "custom" - ] + "$ref": "#/components/schemas/RacingRaceTypeEnum" } }, { @@ -1504,7 +1499,17 @@ "description": "selection id", "required": false, "schema": { - "type": "string" + "oneOf": [ + { + "$ref": "#/components/schemas/UserId" + }, + { + "$ref": "#/components/schemas/TornCrimeId" + }, + { + "type": "string" + } + ] } }, { @@ -1522,10 +1527,23 @@ { "name": "cat", "in": "query", - "description": "Selection category", + "description": "Selection category. Can belong to one of the specified types.", "required": false, "schema": { - "type": "string" + "oneOf": [ + { + "$ref": "#/components/schemas/ReportTypeEnum" + }, + { + "$ref": "#/components/schemas/UserListEnum" + }, + { + "$ref": "#/components/schemas/PersonalStatsCategoryEnum" + }, + { + "$ref": "#/components/schemas/RacingRaceTypeEnum" + } + ] } }, { @@ -1533,8 +1551,13 @@ "in": "query", "description": "Selection stat", "required": false, + "style": "form", + "explode": false, "schema": { - "type": "string" + "type": "array", + "items": { + "$ref": "#/components/schemas/PersonalStatsStatName" + } } }, { @@ -3021,6 +3044,51 @@ "x-stability": "Stable" } }, + "/faction/search": { + "get": { + "tags": [ + "Faction" + ], + "summary": "Search factions by name or other criteria", + "description": "Requires public access key.
This selection is standalone and cannot be used together with other selections.", + "operationId": "01c192f9b41ce29372df54667bea2b43", + "parameters": [ + { + "$ref": "#/components/parameters/ApiName" + }, + { + "$ref": "#/components/parameters/ApiFactionSearchFilter" + }, + { + "$ref": "#/components/parameters/ApiTimestamp" + }, + { + "$ref": "#/components/parameters/ApiComment" + }, + { + "$ref": "#/components/parameters/ApiKeyPublic" + } + ], + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/FactionSearchResponse" + } + } + } + } + }, + "security": [ + { + "api_key": [] + } + ], + "x-stability": "Unstable" + } + }, "/faction/stats": { "get": { "tags": [ @@ -4644,71 +4712,6 @@ "x-stability": "Stable" } }, - "/racing/races": { - "get": { - "tags": [ - "Racing" - ], - "summary": "Get races", - "description": "Requires public access key.
Returns a list of races, ordered by race start timestamp.", - "operationId": "4be921a67d32b5e82c68835ef56175d0", - "parameters": [ - { - "$ref": "#/components/parameters/ApiLimit100" - }, - { - "$ref": "#/components/parameters/ApiSortDesc" - }, - { - "$ref": "#/components/parameters/ApiTo" - }, - { - "$ref": "#/components/parameters/ApiFrom" - }, - { - "name": "cat", - "in": "query", - "description": "Category of races returned", - "required": false, - "schema": { - "type": "string", - "default": "custom", - "enum": [ - "official", - "custom" - ] - } - }, - { - "$ref": "#/components/parameters/ApiTimestamp" - }, - { - "$ref": "#/components/parameters/ApiComment" - }, - { - "$ref": "#/components/parameters/ApiKeyPublic" - } - ], - "responses": { - "200": { - "description": "Successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RacingRacesResponse" - } - } - } - } - }, - "security": [ - { - "api_key": [] - } - ], - "x-stability": "Stable" - } - }, "/racing/{raceId}/race": { "get": { "tags": [ @@ -4960,7 +4963,14 @@ "description": "selection id", "required": false, "schema": { - "type": "string" + "oneOf": [ + { + "$ref": "#/components/schemas/RaceId" + }, + { + "$ref": "#/components/schemas/RaceTrackId" + } + ] } }, { @@ -4981,7 +4991,14 @@ "description": "Selection category", "required": false, "schema": { - "type": "string" + "oneOf": [ + { + "$ref": "#/components/schemas/RacingRaceTypeEnum" + }, + { + "$ref": "#/components/schemas/RaceClassEnum" + } + ] } }, { @@ -5972,7 +5989,26 @@ "description": "selection id", "required": false, "schema": { - "type": "string" + "oneOf": [ + { + "$ref": "#/components/schemas/LogCategoryId" + }, + { + "$ref": "#/components/schemas/TornCrimeId" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/ItemId" + } + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/FactionTerritoryEnum" + } + } + ] } }, { @@ -5996,7 +6032,17 @@ "description": "Selection category", "required": false, "schema": { - "type": "string" + "oneOf": [ + { + "$ref": "#/components/schemas/TornFactionHofCategory" + }, + { + "$ref": "#/components/schemas/TornHofCategory" + }, + { + "$ref": "#/components/schemas/TornItemCategory" + } + ] } }, { @@ -10310,6 +10356,13 @@ "peace" ] }, + "RacingRaceTypeEnum": { + "type": "string", + "enum": [ + "official", + "custom" + ] + }, "FactionPositionAbilityEnum": { "type": "string", "enum": [ @@ -10908,6 +10961,24 @@ 7 ] }, + "Parameters": { + "type": "string", + "oneOf": [ + { + "type": "string", + "enum": [ + "destroyed", + "notDestroyed", + "recruiting", + "notRecruiting" + ] + }, + { + "type": "string", + "pattern": "^(id|respect|members)(Equal|NotEqual|Less|LessOrEqual|GreaterOrEqual|Greater)\\d+$" + } + ] + }, "ReviveSetting": { "type": "string", "enum": [ @@ -12143,6 +12214,22 @@ }, "type": "object" }, + "SelectionCategoryEnum": { + "oneOf": [ + { + "$ref": "#/components/schemas/ReportTypeEnum" + }, + { + "$ref": "#/components/schemas/UserListEnum" + }, + { + "$ref": "#/components/schemas/PersonalStatsCategoryEnum" + }, + { + "$ref": "#/components/schemas/RacingRaceTypeEnum" + } + ] + }, "UserCurrentEducation": { "required": [ "id", @@ -13538,69 +13625,76 @@ "type": "object" }, "UserSelectionName": { - "description": "The following selections will fallback to API v1 and may change at any time: 'ammo','bars','basic','battlestats','bazaar','cooldowns','criminalrecord','discord','display','education','equipment','events','gym','honors','icons','inventory','jobpoints','log','medals','merits','messages','missions','money','networth','newevents','newmessages','notifications','perks','profile','properties','refills','reports','skills','stocks','travel','weaponexp','workstats'.", - "type": "string", - "enum": [ - "attacks", - "attacksfull", - "bounties", - "calendar", - "crimes", - "enlistedcars", - "factionbalance", - "forumfeed", - "forumfriends", - "forumposts", - "forumsubscribedthreads", - "forumthreads", - "hof", - "itemmarket", - "jobranks", - "list", - "lookup", - "organizedcrime", - "personalstats", - "races", - "revives", - "revivesfull", - "timestamp", - "ammo", - "bars", - "basic", - "battlestats", - "bazaar", - "cooldowns", - "criminalrecord", - "discord", - "display", - "education", - "equipment", - "events", - "gym", - "honors", - "icons", - "inventory", - "jobpoints", - "log", - "medals", - "merits", - "messages", - "missions", - "money", - "networth", - "newevents", - "newmessages", - "notifications", - "perks", - "profile", - "properties", - "refills", - "reports", - "skills", - "stocks", - "travel", - "weaponexp", - "workstats" + "oneOf": [ + { + "description": "The following selections will fallback to API v1 and may change at any time: 'ammo','bars','basic','battlestats','bazaar','cooldowns','criminalrecord','discord','display','education','equipment','events','gym','honors','icons','inventory','jobpoints','log','medals','merits','messages','missions','money','networth','newevents','newmessages','notifications','perks','profile','properties','refills','reports','skills','stocks','travel','weaponexp','workstats'.", + "type": "string", + "enum": [ + "attacks", + "attacksfull", + "bounties", + "calendar", + "crimes", + "enlistedcars", + "factionbalance", + "forumfeed", + "forumfriends", + "forumposts", + "forumsubscribedthreads", + "forumthreads", + "hof", + "itemmarket", + "jobranks", + "list", + "lookup", + "organizedcrime", + "personalstats", + "races", + "revives", + "revivesfull", + "timestamp", + "ammo", + "bars", + "basic", + "battlestats", + "bazaar", + "cooldowns", + "criminalrecord", + "discord", + "display", + "education", + "equipment", + "events", + "gym", + "honors", + "icons", + "inventory", + "jobpoints", + "log", + "medals", + "merits", + "messages", + "missions", + "money", + "networth", + "newevents", + "newmessages", + "notifications", + "perks", + "profile", + "properties", + "refills", + "reports", + "skills", + "stocks", + "travel", + "weaponexp", + "workstats" + ] + }, + { + "type": "string" + } ] }, "UserLookupResponse": { @@ -16680,6 +16774,120 @@ }, "type": "object" }, + "FactionSearchLeader": { + "required": [ + "id", + "name" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/UserId" + }, + "name": { + "type": "string" + } + }, + "type": "object" + }, + "FactionSearch": { + "required": [ + "id", + "name", + "respect", + "members", + "leader", + "co_leader", + "image", + "tag_image", + "tag", + "is_destroyed", + "is_recruiting" + ], + "properties": { + "id": { + "$ref": "#/components/schemas/FactionId" + }, + "name": { + "type": "string" + }, + "respect": { + "type": "integer", + "format": "int32" + }, + "members": { + "type": "integer", + "format": "int32" + }, + "leader": { + "$ref": "#/components/schemas/FactionSearchLeader" + }, + "co_leader": { + "oneOf": [ + { + "$ref": "#/components/schemas/FactionSearchLeader" + }, + { + "type": "null" + } + ] + }, + "image": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "tag_image": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "tag": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "is_destroyed": { + "type": "boolean" + }, + "is_recruiting": { + "type": "boolean" + } + }, + "type": "object" + }, + "FactionSearchResponse": { + "required": [ + "search", + "_metadata" + ], + "properties": { + "search": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FactionSearch" + } + }, + "_metadata": { + "$ref": "#/components/schemas/RequestMetadataWithLinks" + } + }, + "type": "object" + }, "FactionTerritoryWarFinished": { "required": [ "id", @@ -18905,57 +19113,56 @@ "type": "object" }, "FactionSelectionName": { - "description": "The following selections will fallback to API v1 and may change at any time: 'armor', 'boosters', 'caches', 'cesium', 'crimeexp', 'drugs', 'medical', 'positions', 'reports', 'temporary', 'weapons'.\n * The following selections are not available in API v2: 'armorynews', 'attacknews', 'crimenews', 'currency', 'donations', 'fundsnews', 'mainnews', 'membershipnews', 'territorynews'.", - "type": "string", - "enum": [ - "applications", - "attacks", - "attacksfull", - "balance", - "basic", - "chain", - "chainreport", - "chains", - "contributors", - "crime", - "crimes", - "hof", - "lookup", - "members", - "news", - "rackets", - "rankedwars", - "rankedwarreport", - "revives", - "revivesfull", - "stats", - "territory", - "territoryownership", - "territorywarreport", - "territorywars", - "timestamp", - "upgrades", - "wars", - "armor", - "boosters", - "caches", - "cesium", - "crimeexp", - "drugs", - "medical", - "positions", - "reports", - "temporary", - "weapons", - "armorynews", - "attacknews", - "crimenews", - "currency", - "donations", - "fundsnews", - "mainnews", - "membershipnews", - "territorynews" + "oneOf": [ + { + "description": "The following selections will fallback to API v1 and may change at any time: 'armor', 'boosters', 'caches', 'cesium', 'crimeexp', 'drugs', 'medical', 'temporary', 'weapons'.\n * The following selections are not available in API v2: 'armorynews', 'attacknews', 'crimenews', 'currency', 'donations', 'fundsnews', 'mainnews', 'membershipnews', 'territorynews'.", + "type": "string", + "enum": [ + "applications", + "attacks", + "attacksfull", + "balance", + "basic", + "chain", + "chainreport", + "chains", + "contributors", + "crime", + "crimes", + "hof", + "lookup", + "members", + "news", + "positions", + "rackets", + "rankedwars", + "rankedwarreport", + "reports", + "revives", + "revivesfull", + "search", + "stats", + "territory", + "territoryownership", + "territorywarreport", + "territorywars", + "timestamp", + "upgrades", + "wars", + "armor", + "boosters", + "caches", + "cesium", + "crimeexp", + "drugs", + "medical", + "temporary", + "weapons" + ] + }, + { + "type": "string" + } ] }, "FactionLookupResponse": { @@ -19669,14 +19876,21 @@ "type": "object" }, "ForumSelectionName": { - "type": "string", - "enum": [ - "categories", - "lookup", - "posts", - "thread", - "threads", - "timestamp" + "oneOf": [ + { + "type": "string", + "enum": [ + "categories", + "lookup", + "posts", + "thread", + "threads", + "timestamp" + ] + }, + { + "type": "string" + } ] }, "ForumLookupResponse": { @@ -19725,6 +19939,9 @@ "type": "integer", "format": "int64" }, + { + "type": "string" + }, { "type": "null" } @@ -19882,10 +20099,17 @@ "type": "object" }, "KeySelectionName": { - "type": "string", - "enum": [ - "info", - "log" + "oneOf": [ + { + "type": "string", + "enum": [ + "info", + "log" + ] + }, + { + "type": "string" + } ] }, "ItemMarketListingItemBonus": { @@ -20102,14 +20326,21 @@ "type": "object" }, "MarketSelectionName": { - "description": "The following selections will fallback to API v1 and may change at any time: 'pointsmarket'.", - "type": "string", - "enum": [ - "itemmarket", - "lookup", - "timestamp", - "pointsmarket", - "bazaar" + "oneOf": [ + { + "description": "The following selections will fallback to API v1 and may change at any time: 'pointsmarket'.", + "type": "string", + "enum": [ + "itemmarket", + "lookup", + "timestamp", + "pointsmarket", + "bazaar" + ] + }, + { + "type": "string" + } ] }, "MarketLookupResponse": { @@ -20650,16 +20881,23 @@ "type": "object" }, "RacingSelectionName": { - "type": "string", - "enum": [ - "cars", - "carupgrades", - "lookup", - "race", - "races", - "records", - "timestamp", - "tracks" + "oneOf": [ + { + "type": "string", + "enum": [ + "cars", + "carupgrades", + "lookup", + "race", + "races", + "records", + "timestamp", + "tracks" + ] + }, + { + "type": "string" + } ] }, "RacingLookupResponse": { @@ -22078,55 +22316,55 @@ "type": "object" }, "TornSelectionName": { - "description": "The following selections will fallback to API v1 and may change at any time: 'bank','cards','cityshops','companies','competition','dirtybombs','gyms','honors','itemdetails','itemstats','medals','organisedcrimes','pawnshop','pokertables','properties','raidreport','raids','rockpaperscissors','searchforcash','shoplifting','stats','stocks'.\n * The following selections are not available in API v2: 'chainreport', 'rackets', 'rankedwarreport', 'rankedwars', 'territorynames', 'territorywarreport', 'territorywars'.", - "type": "string", - "enum": [ - "attacklog", - "bounties", - "calendar", - "crimes", - "education", - "factionhof", - "factiontree", - "hof", - "itemammo", - "itemmods", - "items", - "logcategories", - "logtypes", - "lookup", - "subcrimes", - "territory", - "timestamp", - "bank", - "cards", - "cityshops", - "companies", - "competition", - "dirtybombs", - "gyms", - "honors", - "itemdetails", - "itemstats", - "medals", - "organisedcrimes", - "pawnshop", - "pokertables", - "properties", - "raidreport", - "raids", - "rockpaperscissors", - "searchforcash", - "shoplifting", - "stats", - "stocks", - "chainreport", - "rackets", - "rankedwarreport", - "rankedwars", - "territorynames", - "territorywarreport", - "territorywars" + "oneOf": [ + { + "description": "The following selections will fallback to API v1 and may change at any time: 'bank','cards','cityshops','companies','competition','dirtybombs','gyms','honors','itemdetails','itemstats','medals','organisedcrimes','pawnshop','pokertables','properties','raidreport','raids','rockpaperscissors','searchforcash','shoplifting','stats','stocks'.\n * The following selections are not available in API v2: 'chainreport', 'rackets', 'rankedwarreport', 'rankedwars', 'territorynames', 'territorywarreport', 'territorywars'.", + "type": "string", + "enum": [ + "attacklog", + "bounties", + "calendar", + "crimes", + "education", + "factionhof", + "factiontree", + "hof", + "itemammo", + "itemmods", + "items", + "logcategories", + "logtypes", + "lookup", + "subcrimes", + "territory", + "timestamp", + "bank", + "cards", + "cityshops", + "companies", + "competition", + "dirtybombs", + "gyms", + "honors", + "itemdetails", + "itemstats", + "medals", + "organisedcrimes", + "pawnshop", + "pokertables", + "properties", + "raidreport", + "raids", + "rockpaperscissors", + "searchforcash", + "shoplifting", + "stats", + "stocks" + ] + }, + { + "type": "string" + } ] }, "TornLookupResponse": { @@ -22181,6 +22419,36 @@ "type": "string" } }, + "ApiFactionSearchFilter": { + "name": "filters", + "in": "query", + "description": "A filtering query parameter allowing a comma-separated list of filters.
\n * Each filter can be one of the following:\n * Fixed options: 'destroyed', 'notDestroyed', 'recruiting', 'notRecruiting'\n * Dynamic options: `fieldName`+`condition`+`number`, where:\n * * `fieldName` is one of: `id`, `respect`, `members`\n * * `condition` is one of: `Equal`, `NotEqual`, `Less`, `LessOrEqual`, `GreaterOrEqual`, `Greater`\n * * `number`: any integer value\n * Examples: `filters=destroyed`, `filters=notDestroyed,recruiting`, `filters=respectLessOrEqual20000,idGreater100,notRecruiting`", + "required": false, + "style": "form", + "explode": false, + "schema": { + "type": "array", + "items": { + "schema": "Parameters", + "type": "string", + "oneOf": [ + { + "type": "string", + "enum": [ + "destroyed", + "notDestroyed", + "recruiting", + "notRecruiting" + ] + }, + { + "type": "string", + "pattern": "^(id|respect|members)(Equal|NotEqual|Less|LessOrEqual|GreaterOrEqual|Greater)\\d+$" + } + ] + } + } + }, "ApiComment": { "name": "comment", "in": "query", @@ -22190,6 +22458,15 @@ "type": "string" } }, + "ApiName": { + "name": "name", + "in": "query", + "description": "Name to search for.", + "required": false, + "schema": { + "type": "string" + } + }, "ApiLimit20": { "name": "limit", "in": "query", diff --git a/torn-api/src/scopes.rs b/torn-api/src/scopes.rs index bc3e868..5db9418 100644 --- a/torn-api/src/scopes.rs +++ b/torn-api/src/scopes.rs @@ -9,7 +9,7 @@ pub(super) mod test { use crate::{ executor::{ExecutorExt, ReqwestClient}, models::{ - faction_selection_name::FactionSelectionNameVariant, AttackCode, FactionSelectionName, + faction_selection_name::FactionSelectionNameVariant, AttackCode, PersonalStatsCategoryEnum, PersonalStatsStatName, UserListEnum, }, };