diff --git a/Cargo.lock b/Cargo.lock index 9bd5ca1..4536fa8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1952,6 +1952,7 @@ dependencies = [ "snafu", "tokio", "vapore-proto", + "vapore-struct", ] [[package]] @@ -1971,6 +1972,14 @@ dependencies = [ "protobuf-codegen", ] +[[package]] +name = "vapore-struct" +version = "0.1.0" +dependencies = [ + "bitflags", + "num_enum", +] + [[package]] name = "version_check" version = "0.9.5" diff --git a/Cargo.toml b/Cargo.toml index 4670ed9..298f355 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,14 +4,17 @@ members = [ "client", "lib", "proto", + "struct", ] [workspace.package] version = "0.1.0" [workspace.dependencies] +bitflags = "2.6.0" color-eyre = "0.6" env_logger = "0.11" keyvalues-serde = "0.2" log = "0.4" +num_enum = "0.7.3" protobuf = "3.5.1" diff --git a/lib/Cargo.toml b/lib/Cargo.toml index ab64acd..9e62da5 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -6,14 +6,14 @@ version.workspace = true [dependencies] async-tungstenite = { version = "0.27.0", features = ["tokio-rustls-native-certs"] } base64 = "0.22.1" -bitflags = "2.6.0" +bitflags.workspace = true color-eyre.workspace = true flate2 = "1.0.33" futures = "0.3.30" hex = "0.4.3" keyvalues-serde.workspace = true log.workspace = true -num_enum = "0.7.3" +num_enum.workspace = true protobuf.workspace = true rand = "0.8.5" reqwest = { version = "0.12", features = ["rustls-tls-native-roots"], default-features = false} @@ -22,6 +22,7 @@ serde = { version = "1.0.209", features = ["derive"] } snafu = "0.8.4" tokio = { version = "1.39", features = ["rt", "rt-multi-thread", "macros", "time"]} vapore-proto.path = "../proto" +vapore-struct.path = "../struct" [dev-dependencies] dialoguer = "0.11.0" diff --git a/lib/src/client.rs b/lib/src/client.rs index c3999d0..6a541d0 100644 --- a/lib/src/client.rs +++ b/lib/src/client.rs @@ -15,7 +15,7 @@ use vapore_proto::{ }; use crate::{ - connection::{CMContext, CMSession}, + connection::CMSession, error::{RSAEncryptSnafu, RSAParameterParseSnafu, RSAParseSnafu}, message::CMProtoBufMessage, platform::generate_machine_id, diff --git a/lib/src/error.rs b/lib/src/error.rs index 45ee98d..52bd954 100644 --- a/lib/src/error.rs +++ b/lib/src/error.rs @@ -1,8 +1,5 @@ -use num_enum::TryFromPrimitiveError; use snafu::prelude::*; -use crate::state::apps::{ELicenseType, EPaymentMethod}; - #[derive(Debug, Snafu)] #[snafu(visibility(pub(crate)))] pub enum ClientError { @@ -66,14 +63,9 @@ pub enum ClientError { actual: vapore_proto::enums_clientserver::EMsg, }, - #[snafu(display("Unknown value while parsing enum EPaymentMethod"))] - TryFromEPaymentMethod { - source: TryFromPrimitiveError, - }, - - #[snafu(display("Unknown value while parsing enum ELicenseType"))] - TryFromELicenseType { - source: TryFromPrimitiveError, + #[snafu(display("Unknown value while parsing enum"))] + TryFromPrimitive { + source: Box, }, #[snafu(display("Unable to parse RSA key parameters"))] @@ -92,3 +84,15 @@ impl From> for ClientError { ClientError::LockPoisoned } } + +impl From> + for ClientError +where + ::Primitive: Send + Sync, +{ + fn from(value: num_enum::TryFromPrimitiveError) -> Self { + Self::TryFromPrimitive { + source: Box::new(value), + } + } +} diff --git a/lib/src/state/apps.rs b/lib/src/state/apps.rs index 7d419ce..752b8b1 100644 --- a/lib/src/state/apps.rs +++ b/lib/src/state/apps.rs @@ -3,225 +3,14 @@ use std::{ time::{Duration, SystemTime, UNIX_EPOCH}, }; -use num_enum::TryFromPrimitive; -use snafu::prelude::*; use tokio::sync::watch; use vapore_proto::{ enums_clientserver::EMsg, steammessages_clientserver::{cmsg_client_license_list, CMsgClientLicenseList}, }; +use vapore_struct::enums::{ELicenseFlags, ELicenseType, EPaymentMethod}; -use crate::{ - connection::CMSession, - error::{TryFromELicenseTypeSnafu, TryFromEPaymentMethodSnafu}, - message::{CMProtoBufMessage, CMRawProtoBufMessage}, - ClientError, -}; - -#[repr(u32)] -#[derive(Debug, Copy, Clone, TryFromPrimitive)] -pub enum EPaymentMethod { - None = 0, - ActivationCode = 1, - CreditCard = 2, - Giropay = 3, - PayPal = 4, - Ideal = 5, - PaySafeCard = 6, - Sofort = 7, - GuestPass = 8, - WebMoney = 9, - MoneyBookers = 10, - AliPay = 11, - Yandex = 12, - Kiosk = 13, - Qiwi = 14, - GameStop = 15, - HardwarePromo = 16, - MoPay = 17, - BoletoBancario = 18, - BoaCompraGold = 19, - BancoDoBrasilOnline = 20, - ItauOnline = 21, - BradescoOnline = 22, - Pagseguro = 23, - VisaBrazil = 24, - AmexBrazil = 25, - Aura = 26, - Hipercard = 27, - MastercardBrazil = 28, - DinersCardBrazil = 29, - AuthorizedDevice = 30, - MOLPoints = 31, - ClickAndBuy = 32, - Beeline = 33, - Konbini = 34, - EClubPoints = 35, - CreditCardJapan = 36, - BankTransferJapan = 37, - PayEasy = 38, - Zong = 39, - CultureVoucher = 40, - BookVoucher = 41, - HappymoneyVoucher = 42, - ConvenientStoreVoucher = 43, - GameVoucher = 44, - Multibanco = 45, - Payshop = 46, - MaestroBoaCompra = 47, - OXXO = 48, - ToditoCash = 49, - Carnet = 50, - SPEI = 51, - ThreePay = 52, - IsBank = 53, - Garanti = 54, - Akbank = 55, - YapiKredi = 56, - Halkbank = 57, - BankAsya = 58, - Finansbank = 59, - DenizBank = 60, - PTT = 61, - CashU = 62, - SantanderRio = 63, - AutoGrant = 64, - WebMoneyJapan = 65, - OneCard = 66, - PSE = 67, - Exito = 68, - Efecty = 69, - Paloto = 70, - PinValidda = 71, - MangirKart = 72, - BancoCreditoDePeru = 73, - BBVAContinental = 74, - SafetyPay = 75, - PagoEfectivo = 76, - Trustly = 77, - UnionPay = 78, - BitCoin = 79, - LicensedSite = 80, - BitCash = 81, - NetCash = 82, - Nanaco = 83, - Tenpay = 84, - WeChat = 85, - CashonDelivery = 86, - CreditCardNodwin = 87, - DebitCardNodwin = 88, - NetBankingNodwin = 89, - CashCardNodwin = 90, - WalletNodwin = 91, - MobileDegica = 92, - Naranja = 93, - Cencosud = 94, - Cabal = 95, - PagoFacil = 96, - Rapipago = 97, - BancoNacionaldeCostaRica = 98, - BancoPoplar = 99, - RedPagos = 100, - SPE = 101, - Multicaja = 102, - RedCompra = 103, - ZiraatBank = 104, - VakiflarBank = 105, - KuveytTurkBank = 106, - EkonomiBank = 107, - Pichincha = 108, - PichinchaCash = 109, - Przelewy24 = 110, - Trustpay = 111, - POLi = 112, - MercadoPago = 113, - PayU = 114, - VTCPayWallet = 115, - MrCash = 116, - EPS = 117, - Interac = 118, - VTCPayCards = 119, - VTCPayOnlineBanking = 120, - VisaElectronBoaCompra = 121, - CafeFunded = 122, - OCA = 123, - Lider = 124, - WebMoneySteamCardJapan = 125, - WebMoneySteamCardTopUpJapan = 126, - Toss = 127, - Wallet = 128, - Valve = 129, - MasterComp = 130, - Promotional = 131, - MasterSubscription = 134, - Payco = 135, - MobileWalletJapan = 136, - BoletoFlash = 137, - PIX = 138, - GCash = 139, - KakaoPay = 140, - Dana = 141, - TrueMoney = 142, - TouchnGo = 143, - LinePay = 144, - MerPay = 145, - PayPay = 146, - AlfaClick = 147, - Sberbank = 148, - YooMoney = 149, - Tinkoff = 150, - CashInCIS = 151, - AuPAY = 152, - AliPayHK = 153, - NaverPay = 154, - Linkaja = 155, - ShopeePay = 156, - GrabPay = 157, - PayNow = 158, - OnlineBankingThailand = 159, - CashOptionsThailand = 160, - OEMTicket = 256, - Split = 512, - Complimentary = 1024, - FamilyGroup = 1025, -} - -#[derive(Debug, Copy, Clone, TryFromPrimitive)] -#[repr(u32)] -pub enum ELicenseType { - NoLicense = 0, - SinglePurchase = 1, - SinglePurchaseLimitedUse = 2, - RecurringCharge = 3, - RecurringChargeLimitedUse = 4, - RecurringChargeLimitedUseWithOverages = 5, - RecurringOption = 6, - LimitedUseDelayedActivation = 7, -} - -bitflags::bitflags! { - pub struct ELicenseFlags: u32 { - const None = 0; - const Renew = 0x01; - const RenewalFailed = 0x02; - const Pending = 0x04; - const Expired = 0x08; - const CancelledByUser = 0x10; - const CancelledByAdmin = 0x20; - const LowViolenceContent = 0x40; - const ImportedFromSteam2 = 0x80; - const ForceRunRestriction = 0x100; - const RegionRestrictionExpired = 0x200; - const CancelledByFriendlyFraudLock = 0x400; - const NotActivated = 0x800; - const PendingRefund = 0x2000; - const Borrowed = 0x4000; - const ReleaseStateOverride = 0x8000; - const CancelledByPartner = 0x40000; - const NonPermanent = 0x80000; - const PreferredOwner = 0x100000; - } -} +use crate::{connection::CMSession, message::CMProtoBufMessage, ClientError}; pub struct License { pub package_id: u32, @@ -258,16 +47,10 @@ impl TryFrom for License { }, minute_limit: value.minute_limit(), minutes_used: value.minutes_used(), - payment_method: value - .payment_method() - .try_into() - .context(TryFromEPaymentMethodSnafu {})?, + payment_method: value.payment_method().try_into()?, flags: ELicenseFlags::from_bits_truncate(value.flags()), purchase_country_code: value.purchase_country_code().to_string(), - license_type: value - .license_type() - .try_into() - .context(TryFromELicenseTypeSnafu {})?, + license_type: value.license_type().try_into()?, territory_code: value.territory_code(), change_number: value.change_number(), owner_id: value.owner_id(), diff --git a/proto/src/lib.rs b/proto/src/lib.rs index e3a26bb..af39615 100644 --- a/proto/src/lib.rs +++ b/proto/src/lib.rs @@ -1 +1,5 @@ +//! Generated data types used by the Steam API. +//! This only includes protobufs, not `*.steamd` files representing raw structs +//! and some enums. + include!(concat!(env!("OUT_DIR"), "/gen/mod.rs")); diff --git a/struct/Cargo.toml b/struct/Cargo.toml new file mode 100644 index 0000000..352ff78 --- /dev/null +++ b/struct/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "vapore-struct" +edition = "2021" +version.workspace = true + +[dependencies] +bitflags.workspace = true +num_enum.workspace = true + diff --git a/struct/src/lib.rs b/struct/src/lib.rs new file mode 100644 index 0000000..3970fa1 --- /dev/null +++ b/struct/src/lib.rs @@ -0,0 +1,349 @@ +//! Structures from SteamKit2 `*.steamd` files. +//! Currently these are manually copied, but may be autogenerated in the future + +pub mod eresult { + use num_enum::{IntoPrimitive, TryFromPrimitive}; + #[repr(u32)] + #[derive(Debug, Copy, Clone, TryFromPrimitive, IntoPrimitive)] + enum EResult { + Invalid = 0, + + OK = 1, + Fail = 2, + NoConnection = 3, + InvalidPassword = 5, + LoggedInElsewhere = 6, + InvalidProtocolVer = 7, + InvalidParam = 8, + FileNotFound = 9, + Busy = 10, + InvalidState = 11, + InvalidName = 12, + InvalidEmail = 13, + DuplicateName = 14, + AccessDenied = 15, + Timeout = 16, + Banned = 17, + AccountNotFound = 18, + InvalidSteamID = 19, + ServiceUnavailable = 20, + NotLoggedOn = 21, + Pending = 22, + EncryptionFailure = 23, + InsufficientPrivilege = 24, + LimitExceeded = 25, + Revoked = 26, + Expired = 27, + AlreadyRedeemed = 28, + DuplicateRequest = 29, + AlreadyOwned = 30, + IPNotFound = 31, + PersistFailed = 32, + LockingFailed = 33, + LogonSessionReplaced = 34, + ConnectFailed = 35, + HandshakeFailed = 36, + IOFailure = 37, + RemoteDisconnect = 38, + ShoppingCartNotFound = 39, + Blocked = 40, + Ignored = 41, + NoMatch = 42, + AccountDisabled = 43, + ServiceReadOnly = 44, + AccountNotFeatured = 45, + AdministratorOK = 46, + ContentVersion = 47, + TryAnotherCM = 48, + PasswordRequiredToKickSession = 49, + AlreadyLoggedInElsewhere = 50, + Suspended = 51, + Cancelled = 52, + DataCorruption = 53, + DiskFull = 54, + RemoteCallFailed = 55, + PasswordUnset = 56, + ExternalAccountUnlinked = 57, + PSNTicketInvalid = 58, + ExternalAccountAlreadyLinked = 59, + RemoteFileConflict = 60, + IllegalPassword = 61, + SameAsPreviousValue = 62, + AccountLogonDenied = 63, + CannotUseOldPassword = 64, + InvalidLoginAuthCode = 65, + AccountLogonDeniedNoMail = 66, + HardwareNotCapableOfIPT = 67, + IPTInitError = 68, + ParentalControlRestricted = 69, + FacebookQueryError = 70, + ExpiredLoginAuthCode = 71, + IPLoginRestrictionFailed = 72, + AccountLockedDown = 73, + AccountLogonDeniedVerifiedEmailRequired = 74, + NoMatchingURL = 75, + BadResponse = 76, + RequirePasswordReEntry = 77, + ValueOutOfRange = 78, + UnexpectedError = 79, + Disabled = 80, + InvalidCEGSubmission = 81, + RestrictedDevice = 82, + RegionLocked = 83, + RateLimitExceeded = 84, + AccountLoginDeniedNeedTwoFactor = 85, + ItemDeleted = 86, + AccountLoginDeniedThrottle = 87, + TwoFactorCodeMismatch = 88, + TwoFactorActivationCodeMismatch = 89, + AccountAssociatedToMultiplePartners = 90, + NotModified = 91, + NoMobileDevice = 92, + TimeNotSynced = 93, + SMSCodeFailed = 94, + AccountLimitExceeded = 95, + AccountActivityLimitExceeded = 96, + PhoneActivityLimitExceeded = 97, + RefundToWallet = 98, + EmailSendFailure = 99, + NotSettled = 100, + NeedCaptcha = 101, + GSLTDenied = 102, + GSOwnerDenied = 103, + InvalidItemType = 104, + IPBanned = 105, + GSLTExpired = 106, + InsufficientFunds = 107, + TooManyPending = 108, + NoSiteLicensesFound = 109, + WGNetworkSendExceeded = 110, + AccountNotFriends = 111, + LimitedUserAccount = 112, + CantRemoveItem = 113, + AccountDeleted = 114, + ExistingUserCancelledLicense = 115, + CommunityCooldown = 116, + NoLauncherSpecified = 117, + MustAgreeToSSA = 118, + LauncherMigrated = 119, + SteamRealmMismatch = 120, + InvalidSignature = 121, + ParseFailure = 122, + NoVerifiedPhone = 123, + InsufficientBattery = 124, + ChargerRequired = 125, + CachedCredentialInvalid = 126, + PhoneNumberIsVOIP = 127, + NotSupported = 128, + FamilySizeLimitExceeded = 129, + } +} + +pub mod enums { + use num_enum::{IntoPrimitive, TryFromPrimitive}; + bitflags::bitflags! { + #[derive(Debug, Copy, Clone, PartialEq, Eq)] + pub struct ELicenseFlags: u32 { + const None = 0; + const Renew = 0x01; + const RenewalFailed = 0x02; + const Pending = 0x04; + const Expired = 0x08; + const CancelledByUser = 0x10; + const CancelledByAdmin = 0x20; + const LowViolenceContent = 0x40; + const ImportedFromSteam2 = 0x80; + const ForceRunRestriction = 0x100; + const RegionRestrictionExpired = 0x200; + const CancelledByFriendlyFraudLock = 0x400; + const NotActivated = 0x800; + const PendingRefund = 0x2000; + const Borrowed = 0x4000; + const ReleaseStateOverride = 0x8000; + const CancelledByPartner = 0x40000; + const NonPermanent = 0x80000; + const PreferredOwner = 0x100000; + } + } + + #[derive(Debug, Copy, Clone, TryFromPrimitive, IntoPrimitive)] + #[repr(u32)] + pub enum ELicenseType { + NoLicense = 0, + SinglePurchase = 1, + SinglePurchaseLimitedUse = 2, + RecurringCharge = 3, + RecurringChargeLimitedUse = 4, + RecurringChargeLimitedUseWithOverages = 5, + RecurringOption = 6, + LimitedUseDelayedActivation = 7, + } + + #[repr(u32)] + #[derive(Debug, Copy, Clone, TryFromPrimitive, IntoPrimitive)] + pub enum EPaymentMethod { + None = 0, + ActivationCode = 1, + CreditCard = 2, + Giropay = 3, + PayPal = 4, + Ideal = 5, + PaySafeCard = 6, + Sofort = 7, + GuestPass = 8, + WebMoney = 9, + MoneyBookers = 10, + AliPay = 11, + Yandex = 12, + Kiosk = 13, + Qiwi = 14, + GameStop = 15, + HardwarePromo = 16, + MoPay = 17, + BoletoBancario = 18, + BoaCompraGold = 19, + BancoDoBrasilOnline = 20, + ItauOnline = 21, + BradescoOnline = 22, + Pagseguro = 23, + VisaBrazil = 24, + AmexBrazil = 25, + Aura = 26, + Hipercard = 27, + MastercardBrazil = 28, + DinersCardBrazil = 29, + AuthorizedDevice = 30, + MOLPoints = 31, + ClickAndBuy = 32, + Beeline = 33, + Konbini = 34, + EClubPoints = 35, + CreditCardJapan = 36, + BankTransferJapan = 37, + PayEasy = 38, + Zong = 39, + CultureVoucher = 40, + BookVoucher = 41, + HappymoneyVoucher = 42, + ConvenientStoreVoucher = 43, + GameVoucher = 44, + Multibanco = 45, + Payshop = 46, + MaestroBoaCompra = 47, + OXXO = 48, + ToditoCash = 49, + Carnet = 50, + SPEI = 51, + ThreePay = 52, + IsBank = 53, + Garanti = 54, + Akbank = 55, + YapiKredi = 56, + Halkbank = 57, + BankAsya = 58, + Finansbank = 59, + DenizBank = 60, + PTT = 61, + CashU = 62, + SantanderRio = 63, + AutoGrant = 64, + WebMoneyJapan = 65, + OneCard = 66, + PSE = 67, + Exito = 68, + Efecty = 69, + Paloto = 70, + PinValidda = 71, + MangirKart = 72, + BancoCreditoDePeru = 73, + BBVAContinental = 74, + SafetyPay = 75, + PagoEfectivo = 76, + Trustly = 77, + UnionPay = 78, + BitCoin = 79, + LicensedSite = 80, + BitCash = 81, + NetCash = 82, + Nanaco = 83, + Tenpay = 84, + WeChat = 85, + CashonDelivery = 86, + CreditCardNodwin = 87, + DebitCardNodwin = 88, + NetBankingNodwin = 89, + CashCardNodwin = 90, + WalletNodwin = 91, + MobileDegica = 92, + Naranja = 93, + Cencosud = 94, + Cabal = 95, + PagoFacil = 96, + Rapipago = 97, + BancoNacionaldeCostaRica = 98, + BancoPoplar = 99, + RedPagos = 100, + SPE = 101, + Multicaja = 102, + RedCompra = 103, + ZiraatBank = 104, + VakiflarBank = 105, + KuveytTurkBank = 106, + EkonomiBank = 107, + Pichincha = 108, + PichinchaCash = 109, + Przelewy24 = 110, + Trustpay = 111, + POLi = 112, + MercadoPago = 113, + PayU = 114, + VTCPayWallet = 115, + MrCash = 116, + EPS = 117, + Interac = 118, + VTCPayCards = 119, + VTCPayOnlineBanking = 120, + VisaElectronBoaCompra = 121, + CafeFunded = 122, + OCA = 123, + Lider = 124, + WebMoneySteamCardJapan = 125, + WebMoneySteamCardTopUpJapan = 126, + Toss = 127, + Wallet = 128, + Valve = 129, + MasterComp = 130, + Promotional = 131, + MasterSubscription = 134, + Payco = 135, + MobileWalletJapan = 136, + BoletoFlash = 137, + PIX = 138, + GCash = 139, + KakaoPay = 140, + Dana = 141, + TrueMoney = 142, + TouchnGo = 143, + LinePay = 144, + MerPay = 145, + PayPay = 146, + AlfaClick = 147, + Sberbank = 148, + YooMoney = 149, + Tinkoff = 150, + CashInCIS = 151, + AuPAY = 152, + AliPayHK = 153, + NaverPay = 154, + Linkaja = 155, + ShopeePay = 156, + GrabPay = 157, + PayNow = 158, + OnlineBankingThailand = 159, + CashOptionsThailand = 160, + OEMTicket = 256, + Split = 512, + Complimentary = 1024, + FamilyGroup = 1025, + } +}