4242import jd .plugins .PluginForHost ;
4343import jd .utils .JDUtilities ;
4444
45- @ DecrypterPlugin (revision = "$Revision: 50039 $" , interfaceVersion = 3 , names = { "nexusmods.com" }, urls = { "https?://(?:www\\ .)?nexusmods\\ .com/(?!contents)([^/]+)/mods/(\\ d+)/?" })
45+ @ DecrypterPlugin (revision = "$Revision: 50040 $" , interfaceVersion = 3 , names = { "nexusmods.com" }, urls = { "https?://(?:www\\ .)?nexusmods\\ .com/(?!contents)([^/]+)/mods/(\\ d+)/?" })
4646public class NexusmodsComCrawler extends PluginForDecrypt {
4747 public NexusmodsComCrawler (PluginWrapper wrapper ) {
4848 super (wrapper );
@@ -65,7 +65,7 @@ public ArrayList<DownloadLink> decryptIt(final CryptedLink param, ProgressContro
6565 if (apikey != null ) {
6666 ret = crawlAPI (param , account , game_domain_name , mod_id );
6767 } else {
68- ret = crawlWebsite (param , account , game_domain_name , mod_id );
68+ ret = crawlWebsite (param , game_domain_name , mod_id );
6969 }
7070 return ret ;
7171 }
@@ -133,14 +133,10 @@ private ArrayList<DownloadLink> crawlAPI(final CryptedLink param, final Account
133133 return ret ;
134134 }
135135
136- private ArrayList <DownloadLink > crawlWebsite (final CryptedLink param , final Account account , final String game_domain_name , final String mod_id ) throws Exception {
136+ /** Crawls items from website (without account). */
137+ private ArrayList <DownloadLink > crawlWebsite (final CryptedLink param , final String game_domain_name , final String mod_id ) throws Exception {
137138 final String parameter = param .getCryptedUrl ();
138139 final PluginForHost plugin = JDUtilities .getPluginForHost (this .getHost ());
139- final ArrayList <DownloadLink > ret = new ArrayList <DownloadLink >();
140- if (account != null ) {
141- /* Login via website */
142- ((jd .plugins .hoster .NexusmodsCom ) plugin ).loginWebsite (account );
143- }
144140 br .setFollowRedirects (true );
145141 ((jd .plugins .hoster .NexusmodsCom ) plugin ).getPage (br , parameter );
146142 if (jd .plugins .hoster .NexusmodsCom .isOfflineWebsite (br )) {
@@ -152,6 +148,7 @@ private ArrayList<DownloadLink> crawlWebsite(final CryptedLink param, final Acco
152148 logger .info ("Adult content: Enable it in your account settings to be able to download such files via JD: Profile --> Settings --> Content blocking --> Show adult content" );
153149 throw new AccountRequiredException ("Adult content: Enable it in your account settings to be able to download such files via JD: Profile --> Settings --> Content blocking --> Show adult content" );
154150 }
151+ final ArrayList <DownloadLink > ret = new ArrayList <DownloadLink >();
155152 String mod_name = br .getRegex ("<meta property=\" og:title\" content=\" ([^<>\" ]+)\" " ).getMatch (0 );
156153 if (mod_name == null ) {
157154 /* This should never happen */
@@ -164,61 +161,91 @@ private ArrayList<DownloadLink> crawlWebsite(final CryptedLink param, final Acco
164161 final Browser br2 = br .cloneBrowser ();
165162 ((jd .plugins .hoster .NexusmodsCom ) plugin ).getPage (br2 , "/" + game_domain_name + "/mods/" + mod_id + "?tab=files" );
166163 final String [] categoryNames = br2 .getRegex ("<div class=\" file-category-header\" >\\ s*<h2>([^>]+)</h2>" ).getColumn (0 );
167- final String [] downloadCategoriesHTMLs = br2 .getRegex ("<dd[^>]* data-id=\" \\ d+\" [^>]*>.*?</div>\\ s*</dt>" ).getColumn (-1 );
168- if (downloadCategoriesHTMLs == null || downloadCategoriesHTMLs .length == 0 ) {
164+ final String [] downloadCategoriesHTMLs = br2 .getRegex ("<dd[^>]*data-id=\" \\ d+\" [^>]*>.*?</div>\\ s*</dt>" ).getColumn (-1 );
165+ String description = br2 .getRegex ("<meta name=\" description\" content=\" ([^\" ]+)" ).getMatch (0 );
166+ if (downloadCategoriesHTMLs != null && downloadCategoriesHTMLs .length > 0 ) {
167+ int index = -1 ;
168+ for (final String downnloadTypeHTML : downloadCategoriesHTMLs ) {
169+ index ++;
170+ String category_name = null ;
171+ if (categoryNames != null && categoryNames .length == downloadCategoriesHTMLs .length ) {
172+ category_name = categoryNames [index ];
173+ }
174+ category_name = Encoding .htmlDecode (category_name ).trim ();
175+ ret .addAll (websiteCrawlFiles (downnloadTypeHTML , category_name , index , mod_id , game_id , game_domain_name , mod_name ));
176+ }
177+ } else {
178+ /* Fallback: Don't care about the categories, just find the files */
179+ logger .warning ("Failed to find categories" );
180+ ret .addAll (websiteCrawlFiles (br2 .getRequest ().getHtmlCode (), null , 0 , mod_id , game_id , game_domain_name , mod_name ));
181+ }
182+ if (ret .isEmpty ()) {
183+ /*
184+ * Effectively, items are only downloadable via (paid) account so if the crawler fails, let's suppress that and instead ask the
185+ * user to retry again with account -> User can then use the API so then the crawler will work fine.
186+ */
187+ // throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT, "Failed to find game_id");
188+ throw new AccountRequiredException ();
189+ }
190+ if (description != null ) {
191+ /* Set description as package comment. */
192+ description = Encoding .htmlDecode (description ).trim ();
193+ for (final DownloadLink link : ret ) {
194+ if (link .getFilePackage () == null ) {
195+ continue ;
196+ }
197+ link .getFilePackage ().setComment (description );
198+ }
199+ }
200+ return ret ;
201+ }
202+
203+ private List <DownloadLink > websiteCrawlFiles (final String html_source , final String category_name , final int categoryIndex , final String mod_id , final String game_id , final String game_domain_name , final String mod_name ) throws PluginException {
204+ final ArrayList <DownloadLink > ret = new ArrayList <DownloadLink >();
205+ final FilePackage fp = FilePackage .getInstance ();
206+ if (category_name != null ) {
207+ fp .setName (game_domain_name + " - " + mod_name + " - " + category_name );
208+ } else {
209+ fp .setName (game_domain_name + " - " + mod_name );
210+ }
211+ final String currentPath = game_domain_name + "/" + mod_name + "/" + category_name ;
212+ final String [] htmls = new Regex (html_source , "<dt id=\" file-expander-header-\\ d+\" .*?/use>\\ s*</svg>\\ s*</div>" ).getColumn (-1 );
213+ if (htmls == null || htmls .length == 0 ) {
169214 throw new PluginException (LinkStatus .ERROR_PLUGIN_DEFECT );
170215 }
171- int index = -1 ;
172- for (final String downnloadTypeHTML : downloadCategoriesHTMLs ) {
173- index ++;
174- String category_name = null ;
175- if (categoryNames != null && categoryNames .length == downloadCategoriesHTMLs .length ) {
176- category_name = categoryNames [index ];
216+ for (final String html : htmls ) {
217+ String file_id = new Regex (html , "\\ ?id=(\\ d+)" ).getMatch (0 );
218+ if (file_id == null ) {
219+ file_id = new Regex (html , "data-id=\" (\\ d+)\" " ).getMatch (0 );
177220 }
178- if (category_name == null ) {
179- /* Fallback */
180- category_name = "Unknown_category_" + ( index + 1 ) ;
221+ if (file_id == null ) {
222+ logger . info ( "file_id is null" );
223+ continue ;
181224 }
182- final FilePackage fp = FilePackage .getInstance ();
183- fp .setName (game_domain_name + " - " + mod_name + " - " + category_name );
184- category_name = Encoding .htmlDecode (category_name ).trim ();
185- final String currentPath = game_domain_name + "/" + mod_name + "/" + category_name ;
186- final String [] htmls = new Regex (downnloadTypeHTML , "<dt id=\" file-expander-header-\\ d+\" .*?/use>\\ s*</svg>\\ s*</div>" ).getColumn (-1 );
187- if (htmls == null || htmls .length == 0 ) {
188- throw new PluginException (LinkStatus .ERROR_PLUGIN_DEFECT );
225+ final String filename = new Regex (html , "data-url=\" ([^<>\" ]+)\" " ).getMatch (0 );
226+ final DownloadLink link = createDownloadlink (generatePluginPatternMatcher (file_id , game_id ));
227+ link .setContentUrl (generateContentURL (game_domain_name , mod_id , file_id ));
228+ final String filesizeStr = new Regex (html , ">\\ s*File\\ s*size\\ s*</div>.*?\" stat\" \\ s*>\\ s*([0-9\\ .TKGMB]+)" ).getMatch (0 );
229+ if (filesizeStr != null ) {
230+ link .setDownloadSize (SizeFormatter .getSize (filesizeStr ));
189231 }
190- for (final String html : htmls ) {
191- String file_id = new Regex (html , "\\ ?id=(\\ d+)" ).getMatch (0 );
192- if (file_id == null ) {
193- file_id = new Regex (html , "data-id=\" (\\ d+)\" " ).getMatch (0 );
194- }
195- if (file_id == null ) {
196- logger .info ("file_id is null" );
197- continue ;
198- }
199- final String filename = new Regex (html , "data-url=\" ([^<>\" ]+)\" " ).getMatch (0 );
200- final DownloadLink link = createDownloadlink (generatePluginPatternMatcher (file_id , game_id ));
201- link .setContentUrl (generateContentURL (game_domain_name , mod_id , file_id ));
202- final String filesizeStr = new Regex (html , ">\\ s*File\\ s*size\\ s*</div>.*?\" stat\" \\ s*>\\ s*([0-9\\ .TKGMB]+)" ).getMatch (0 );
203- if (filesizeStr != null ) {
204- link .setDownloadSize (SizeFormatter .getSize (filesizeStr ));
205- }
206- if (filename != null ) {
207- link .setName (file_id + "_" + Encoding .htmlOnlyDecode (filename ));
208- } else {
209- link .setName (file_id );
210- }
211- link .setAvailable (true );
212- link .setMimeHint (CompiledFiletypeFilter .ArchiveExtensions .ZIP );
213- link .setRelativeDownloadFolderPath (currentPath );
214- link ._setFilePackage (fp );
215- /* Important! These properties are especially required for all API requests! */
216- link .setProperty ("game_domain_name" , game_domain_name );
217- link .setProperty ("mod_id" , mod_id );
232+ if (filename != null ) {
233+ link .setName (file_id + "_" + Encoding .htmlOnlyDecode (filename ));
234+ } else {
235+ link .setName (file_id );
236+ }
237+ link .setAvailable (true );
238+ link .setMimeHint (CompiledFiletypeFilter .ArchiveExtensions .ZIP );
239+ link .setRelativeDownloadFolderPath (currentPath );
240+ link ._setFilePackage (fp );
241+ /* Important! These properties are especially required for all API requests! */
242+ link .setProperty ("game_domain_name" , game_domain_name );
243+ link .setProperty ("mod_id" , mod_id );
244+ if (category_name != null ) {
218245 /* Every category goes into a subfolder */
219246 link .setRelativeDownloadFolderPath (game_domain_name + "/" + category_name );
220- ret .add (link );
221247 }
248+ ret .add (link );
222249 }
223250 return ret ;
224251 }
0 commit comments