Skip to content

Commit

Permalink
Direct Download "Browse" files when possible (in collections) (#2198)
Browse files Browse the repository at this point in the history
* Add support for downloading "browse" files as "direct" files when we can determine that the files are direct-downloadable

* Accept anything that's `application/` instead of just octet-streams
  • Loading branch information
halgari authored Oct 24, 2024
1 parent 449edf7 commit 3b34921
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace NexusMods.Abstractions.Collections.Json;
/// </summary>
public enum ModSourceType
{
browse,
direct,
nexus,
bundle,
Expand Down
31 changes: 30 additions & 1 deletion src/NexusMods.Collections/InstallCollectionJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ private async Task<ModInstructions> EnsureDownloaded(Mod mod)
{
return mod.Source.Type switch
{
ModSourceType.browse => await EnsureBrowseModIsDirectDownloaded(mod),
ModSourceType.direct => await EnsureDirectMod(mod),
ModSourceType.nexus => await EnsureNexusModDownloaded(mod),
// Nothing to downoad for a bundle
Expand All @@ -426,7 +427,35 @@ private async Task<ModInstructions> EnsureDownloaded(Mod mod)
};
}


private async Task<ModInstructions> EnsureBrowseModIsDirectDownloaded(Mod mod)
{
var db = Connection.Db;
if (DirectDownloadLibraryFile.FindByMd5(db, mod.Source.Md5).TryGetFirst(out var found))
return (mod, found.AsLibraryFile());

// There's a small chance that the file may be downloadable via a direct download, so we'll try that
// by getting doing a HEAD request to the URL and checking the content type/size

var request = new HttpRequestMessage(HttpMethod.Head, mod.Source.Url);
using var response = await SerivceProvider.GetRequiredService<HttpClient>().SendAsync(request);
if (!response.IsSuccessStatusCode)
throw new InvalidOperationException("The mod could not be downloaded.");

var contentType = response.Content.Headers.ContentType?.MediaType;
if (contentType is null || !contentType.StartsWith("application/"))
throw new InvalidOperationException("The mod is not a direct download.");

if (!response.Content.Headers.ContentLength.HasValue)
throw new InvalidOperationException("The mod does not have a content length.");

var size = Size.FromLong(response.Content.Headers.ContentLength.Value);
if (size != mod.Source.FileSize)
throw new InvalidOperationException("The mod's file size does not match the expected size.");

return await EnsureDirectMod(mod);
}


private async Task<ModInstructions> EnsureDirectMod(Mod mod)
{
var db = Connection.Db;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
{
mods: [
Game Files,
Halgari's Helper,
My Mods
],
files: {
(Appearance Menu Mod, {Game}/archive/pc/mod/_1_Ves_HanakoFixedBodyNaked.archive): 0xBB5F35096990DEBD,
(Appearance Menu Mod, {Game}/archive/pc/mod/AMM_Dino_TattooFix.archive): 0x1D13EF6635D57EDE,
(Appearance Menu Mod, {Game}/archive/pc/mod/AMM_RitaWheeler_CombatEnabler.archive): 0x8CBF54A91B28B524,
(Appearance Menu Mod, {Game}/archive/pc/mod/AMM_Songbird_BodyFix.archive): 0x3189C6C435A869A0,
(Appearance Menu Mod, {Game}/archive/pc/mod/basegame_AMM_BenjaminStonePP.archive): 0xB1A1C3A5387CC01E,
(Appearance Menu Mod, {Game}/archive/pc/mod/basegame_AMM_Delamain_Fix.archive): 0xD7927551B67E68AE,
(Appearance Menu Mod, {Game}/archive/pc/mod/basegame_AMM_JudyBodyRevamp.archive): 0x4CA1826BA1685FCC,
(Appearance Menu Mod, {Game}/archive/pc/mod/basegame_AMM_LizzyIncognito.archive): 0xADF392AFDE79C961,
(Appearance Menu Mod, {Game}/archive/pc/mod/basegame_AMM_MeredithXtra.archive): 0x05D34333864E1307,
(Appearance Menu Mod, {Game}/archive/pc/mod/basegame_AMM_PanamBodyRevamp.archive): 0x6425BF418B3C16D8,
(Appearance Menu Mod, {Game}/archive/pc/mod/basegame_AMM_Props.archive): 0x14891A7910BC8983,
(Appearance Menu Mod, {Game}/archive/pc/mod/basegame_AMM_requirement.archive): 0xA8CEDFD5D46811BB,
(Appearance Menu Mod, {Game}/archive/pc/mod/basegame_AMM_SoundEffects.archive): 0x72BB4A815690C128,
(Appearance Menu Mod, {Game}/archive/pc/mod/basegame_johnny_companion.archive): 0x24C9E2AB595AD674,
(Appearance Menu Mod, {Game}/archive/pc/mod/basegame_texture_HanakoNoMakeup.archive): 0xCC74158AC3676C96,
(Appearance Menu Mod, {Game}/archive/pc/mod/PinkyDude_ANIM_FacialExpressions_FemaleV.archive): 0xE0EBCDE19E41AFBB,
(Appearance Menu Mod, {Game}/archive/pc/mod/PinkyDude_ANIM_FacialExpressions_MaleV.archive): 0xFF1DE5E3A461CFC1,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Collabs/API.lua): 0x036EE6E2DBDF9A6E,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Collabs/Custom Appearances/vortex_needs_this.txt): 0x7E95CD44BB7CBFC3,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Collabs/Custom Entities/vortex_needs_this.txt): 0x7E95CD44BB7CBFC3,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Collabs/Custom Poses/vortex_needs_this.txt): 0x7E95CD44BB7CBFC3,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Collabs/Custom Props/vortex_needs_this.txt): 0x7E95CD44BB7CBFC3,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/credits.lua): 0xC760E3BA4E60D83B,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/db.sqlite3): 0x1C00C2F57AD6B0A3,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/External/Cron.lua): 0x5A53BE3BEDE7DE9B,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/External/GameSession.lua): 0x455AEAF7EC3FEB64,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/External/GameSettings.lua): 0x0723E902C7C7E59D,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/External/Inspect.lua): 0xFFEC432FF2204461,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/init.lua): 0x21B416CA500935DF,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Localization/en_US.lua): 0xEFE66C695C24D634,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Localization/tr_TR.lua): 0x64707D9DDC8637B0,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Localization/zh_CN.lua): 0xDB31B3F65D522F42,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Modules/anims.lua): 0x595E3C6A7B788058,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Modules/camera.lua): 0x4FB93DDC51A562CF,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Modules/director.lua): 0xFFC7ECEDFD1F5344,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Modules/entity.lua): 0xBEDF6CE3220862D3,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Modules/light.lua): 0x9D7F318534D0BC2F,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Modules/props.lua): 0x681408A9F4BC30EA,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Modules/scan.lua): 0x56F0E0A033AF62C3,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Modules/spawn.lua): 0x4ADDF13907B62BEC,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Modules/swap.lua): 0xCFFB5DF9AB293EBB,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Modules/tools.lua): 0x968E7EA10BE89073,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Modules/util.lua): 0x6F9C3B854B0BD42D,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Themes/Computer Blue.json): 0xB12B62417FB5B162,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Themes/Cyberpunk.json): 0xF38D7D9A556A5E15,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Themes/Default.json): 0x04E09F3816AB8021,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Themes/Deus Ex.json): 0x9772C191263CB5FA,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Themes/editor.lua): 0xF774606BA78569BC,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Themes/Midori.json): 0xB60DEFB058518B9F,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Themes/Original.json): 0x58FDFDA3FB499B6A,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Themes/Purpura.json): 0xD334462D20ADA9C6,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Themes/Silverhand.json): 0x6E9B2A2685C22B64,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/Themes/ui.lua): 0x9918D8611006D446,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/update_notes.lua): 0xE2C526B0268E15DD,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/User/Decor/Backup/vortex_needs_this.txt): 0x7E95CD44BB7CBFC3,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/User/Decor/vortex_needs_this.txt): 0x7E95CD44BB7CBFC3,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/User/Locations/vortex_needs_this.txt): 0x7E95CD44BB7CBFC3,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/User/Scripts/Judy and Nibbles - Mansion.json): 0x70A567A5405976A1,
(Appearance Menu Mod, {Game}/bin/x64/plugins/cyber_engine_tweaks/mods/AppearanceMenuMod/User/Themes/vortex_needs_this.txt): 0x7E95CD44BB7CBFC3,
(bundle_mod.zip.zip, {Game}/archive/pc/mod/bundled_image.png.png): 0x5BA312B604217419,
(Butter My V - Sweaty 25, {Game}/archive/pc/mod/basegame_mod_Sweaty25_07.archive): 0x777B30B04FD846BE,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/global.ini): 0xB22A6D4E2D34E07F,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/LICENSE): 0xF0EAC30BF20A745D,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks.asi): 0x9EA23A909A8633E4,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/materialdesignicons.ttf): 0xE51054EFE50C90F7,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSans-Regular.ttf): 0x51FAB10D52D8AC2A,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansJP-Regular.otf): 0x62923066950CC93D,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansKR-Regular.otf): 0x6A56DCD0357B68DD,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansMono-Regular.ttf): 0xE9EAEBF0C477EB65,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansSC-Regular.otf): 0x255F1F653A417F73,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansTC-Regular.otf): 0x2DD3463A6829EB72,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansThai-Regular.ttf): 0x2363F66B2B12ADEE,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/scripts/IconGlyphs/icons.lua): 0x83670A28392FA2B2,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/scripts/json/json.lua): 0xF61FD8C77D020E6C,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/scripts/json/LICENSE): 0x564B031D3D73FECD,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/scripts/json/README.md): 0x681672917A36119B,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/ThirdParty_LICENSES): 0xB62A1399EF1C38F1,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/tweakdb/tweakdbstr.kark): 0x0CE4F15227C0D8AB,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/plugins/cyber_engine_tweaks/tweakdb/usedhashes.kark): 0xD8E8A1699A4B7739,
(CET 1.33.0 - Game patch 2.13 support, {Game}/bin/x64/version.dll): 0xD0648A2A863844C3,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/global.ini): 0xB22A6D4E2D34E07F,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks.asi): 0xC96916A428DF153E,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/materialdesignicons.ttf): 0xE51054EFE50C90F7,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSans-Regular.ttf): 0x51FAB10D52D8AC2A,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansJP-Regular.otf): 0x62923066950CC93D,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansKR-Regular.otf): 0x6A56DCD0357B68DD,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansMono-Regular.ttf): 0xE9EAEBF0C477EB65,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansSC-Regular.otf): 0x255F1F653A417F73,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansTC-Regular.otf): 0x2DD3463A6829EB72,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/fonts/NotoSansThai-Regular.ttf): 0x2363F66B2B12ADEE,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/scripts/IconGlyphs/icons.lua): 0x83670A28392FA2B2,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/scripts/json/json.lua): 0xF61FD8C77D020E6C,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/scripts/json/LICENSE): 0x564B031D3D73FECD,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/scripts/json/README.md): 0x681672917A36119B,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/ThirdParty_LICENSES): 0xB62A1399EF1C38F1,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/tweakdb/tweakdbstr.kark): 0x0CE4F15227C0D8AB,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/plugins/cyber_engine_tweaks/tweakdb/usedhashes.kark): 0xD8E8A1699A4B7739,
(Cyber Engine Tweaks - CET 1.32.2, {Game}/bin/x64/version.dll): 0xD0648A2A863844C3,
(Load Begone (Intro Splash Load and Checkpoint Removal - FOMOD) - Load Begone - 2.2.1 (FOMOD), {Game}/archive/pc/mod/LoadBegone2-Checkpoints.archive): 0x8AC3E1E0A1E0C750,
(Load Begone (Intro Splash Load and Checkpoint Removal - FOMOD) - Load Begone - 2.2.1 (FOMOD), {Game}/archive/pc/mod/LoadBegone2-NoIntroVideo.archive): 0x5099B3BA724BCB7F,
(Load Begone (Intro Splash Load and Checkpoint Removal - FOMOD) - Load Begone - 2.2.1 (FOMOD), {Game}/archive/pc/mod/LoadBegone2.archive): 0x81EC278CDBFEEF4C,
(redscript, {Game}/engine/config/base/scripts.ini): 0xCDE2B2CADCFD3094,
(redscript, {Game}/engine/tools/scc_lib.dll): 0x2F8082F4425E6765,
(redscript, {Game}/engine/tools/scc.exe): 0x2108892FF195B88D,
(redscript, {Game}/r6/config/cybercmd/scc.toml): 0x4CBBB4E06F8C0B29
}
}
2 changes: 2 additions & 0 deletions tests/NexusMods.Collections.Tests/CollectionInstallTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public class CollectionInstallTests(ITestOutputHelper helper) : ACyberpunkIsolat
[InlineData("jjctqn", 4)]
// Includes direct download mod
[InlineData("jjctqn", 5)]
// Includes a browse mod that can be downloaded directly
[InlineData("jjctqn", 6)]
public async Task CanInstallCollections(string slug, int revisionNumber)
{
await using var destination = TemporaryFileManager.CreateFile();
Expand Down

0 comments on commit 3b34921

Please sign in to comment.