Repository: Jackett/Jackett
Pull request #15910: Add Phoenix Project
Author: login: NohamR
Created: 2025-03-12T21:59:12Z | Merged: 2025-03-12T22:46:26Z

#### Description
Add support for Phoenix Project tracker


Diff:
diff --git a/README.md b/README.md
index 813e681d4fe0d..8a4ebf5582c67 100644
--- a/README.md
+++ b/README.md
@@ -489,6 +489,7 @@ Prior versions of Jackett are no longer supported.
  * PassThePopcorn (PTP) [![(invite needed)][inviteneeded]](#)
  * Peeratiko
  * Peers.FM
+ * Phoenix Project [![(invite needed)][inviteneeded]](#)
  * PigNetwork (猪猪网)
  * PixelCove (Ultimate Gamer)
  * PiXELHD (PxHD) [![(invite needed)][inviteneeded]](#)
diff --git a/src/Jackett.Common/Indexers/Definitions/PhoenixProject.cs b/src/Jackett.Common/Indexers/Definitions/PhoenixProject.cs
new file mode 100644
index 0000000000000..6cdb95153acbf
--- /dev/null
+++ b/src/Jackett.Common/Indexers/Definitions/PhoenixProject.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using Jackett.Common.Indexers.Definitions.Abstract;
+using Jackett.Common.Models;
+using Jackett.Common.Services.Interfaces;
+using NLog;
+using static Jackett.Common.Models.IndexerConfig.ConfigurationData;
+using WebClient = Jackett.Common.Utils.Clients.WebClient;
+
+namespace Jackett.Common.Indexers.Definitions
+{
+    [ExcludeFromCodeCoverage]
+    public class PhoenixProject : GazelleTracker
+    {
+        public override string Id => "phoenixproject";
+        public override string Name => "Phoenix Project";
+        public override string Description => "MacOS software tracker";
+        public override string SiteLink { get; protected set; } = "https://phoenixproject.app/";
+        public override string Language => "en-US";
+        public override string Type => "private";
+
+        public override TorznabCapabilities TorznabCaps => SetCapabilities();
+
+        protected override string AuthorizationFormat => "token {0}";
+        protected override int ApiKeyLength => 118;
+
+        public PhoenixProject(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps, ICacheService cs)
+            : base(configService: configService,
+                   client: wc,
+                   logger: l,
+                   p: ps,
+                   cs: cs,
+                   supportsFreeleechTokens: true,
+                   useApiKey: true,
+                   instructionMessageOptional: "<ol><li>Go to PhoenixProject's site and open your account settings.</li><li>Go to <b>Access Settings</b> tab use the <b>API Keys: click here to create a new token</b> link.</li><li>Give it a name and click <b>Generate</b>.</li><li>Finally, copy/paste the token to your Jackett config APIKey input box.</li></ol>"
+                )
+        {
+            configData.AddDynamic("Account Inactivity", new DisplayInfoConfigurationItem("Account Inactivity", "To keep your account active, sign in and browse the site at least once every 120 days. Seeding torrents does not count as account activity, so in order to remain active you need to sign in and browse the site. Power Users (and above) are immune to the inactivity timer, but logging in regularly is recommended to learn about special events and new features. Donors are exempt from automatic account disabling due to inactivity. If you wish to always maintain an active account consider donating."));
+        }
+
+        protected override string FlipOptionalTokenString(string requestLink) => requestLink.Replace("&usetoken=1", "");
+
+        private TorznabCapabilities SetCapabilities()
+        {
+            var caps = new TorznabCapabilities
+            {
+                MusicSearchParams = new List<MusicSearchParam>
+                {
+                    MusicSearchParam.Q
+                }
+            };
+
+            caps.Categories.AddCategoryMapping(1, TorznabCatType.PCMac, "Applications");
+            caps.Categories.AddCategoryMapping(2, TorznabCatType.PCGames, "Games");
+            caps.Categories.AddCategoryMapping(3, TorznabCatType.PCMobileiOS, "IOS Applications");
+            caps.Categories.AddCategoryMapping(4, TorznabCatType.PCMobileiOS, "IOS Games");
+            caps.Categories.AddCategoryMapping(5, TorznabCatType.Other, "Graphics");
+            caps.Categories.AddCategoryMapping(6, TorznabCatType.Audio, "Audio");
+            caps.Categories.AddCategoryMapping(7, TorznabCatType.Other, "Tutorials");
+            caps.Categories.AddCategoryMapping(8, TorznabCatType.Other, "Other");
+
+            return caps;
+        }
+
+        protected override Uri GetDownloadUrl(int torrentId, bool canUseToken)
+        {
+            return new Uri($"{SiteLink}ajax.php?action=download{(useTokens && canUseToken ? "&usetoken=1" : "")}&id={torrentId}");
+        }
+    }
+}


Reviews:
user: login: garfield69
body: Thank you for your contribution
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T22:24:35Z
user: login: NohamR
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T22:36:09Z
user: login: garfield69
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T22:39:04Z

Review comments:
diff_hunk: @@ -406,6 +406,7 @@ Prior versions of Jackett are no longer supported.
  * House of Devil
  * HUDBT (蝴蝶) [![(invite needed)][inviteneeded]](#)
  * iAnon
+ * Phoenix Project [![(invite needed)][inviteneeded]](#)
path: README.md
user: login: garfield69
body: The private list is alphabetical, please move this entry to the correct line. Thanks.
created_at: 2025-03-12T22:12:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -406,6 +406,7 @@ Prior versions of Jackett are no longer supported.
  * House of Devil
  * HUDBT (蝴蝶) [![(invite needed)][inviteneeded]](#)
  * iAnon
+ * Phoenix Project [![(invite needed)][inviteneeded]](#)
path: README.md
user: login: NohamR
body: Sorry, fixed
created_at: 2025-03-12T22:36:09Z
author_association: CONTRIBUTOR

PR comments:
user: login: garfield69
created_at: 2025-03-13T05:53:26Z
body: v0.22.1595
author_association: CONTRIBUTOR
user: login: ilike2burnthing
created_at: 2025-03-14T03:30:16Z
body: @NohamR, keywordless search is returning only 5 results and keyword search returns the same 292 results, no matter what is searched.

Are you seeing the same behaviour? If so, can you take a second look at this? Thanks!
author_association: CONTRIBUTOR
user: login: ilike2burnthing
created_at: 2025-03-14T04:00:46Z
body: @garfield69 I just noticed none of the GazelleTracker indexers have MRs or MSTs. Is there a reason for this? The ratio rules page for this one has both (0.6 and 72hrs).
author_association: CONTRIBUTOR
user: login: garfield69
created_at: 2025-03-14T04:11:18Z
body: Look at greatposterwall, alpharatio, gazellegamesapi for examples.
Any others that should have MR or/and MST and do not, are likely an oversight. 
[edit] added more findings.
author_association: CONTRIBUTOR
user: login: ilike2burnthing
created_at: 2025-03-14T04:31:52Z
body: 🤦 clearly I'm blind, thanks!

@NohamR if you can add these as well (`0.6` and `259200` respectively):

https://github.com/Jackett/Jackett/blob/630c99626d475f2acd0186972b48c7eb8a302a5a/src/Jackett.Common/Indexers/Definitions/AlphaRatio.cs#L88-L97
author_association: CONTRIBUTOR