mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-17 17:14:18 +02:00
New: Rewrite Indexer Flags Implementation
This commit is contained in:
@@ -7,7 +7,7 @@ import { saveDimensions, setIsSidebarVisible } from 'Store/Actions/appActions';
|
|||||||
import { fetchCustomFilters } from 'Store/Actions/customFilterActions';
|
import { fetchCustomFilters } from 'Store/Actions/customFilterActions';
|
||||||
import { fetchIndexers } from 'Store/Actions/indexerActions';
|
import { fetchIndexers } from 'Store/Actions/indexerActions';
|
||||||
import { fetchIndexerStatus } from 'Store/Actions/indexerStatusActions';
|
import { fetchIndexerStatus } from 'Store/Actions/indexerStatusActions';
|
||||||
import { fetchGeneralSettings, fetchIndexerCategories, fetchIndexerFlags, fetchLanguages, fetchUISettings } from 'Store/Actions/settingsActions';
|
import { fetchGeneralSettings, fetchIndexerCategories, fetchLanguages, fetchUISettings } from 'Store/Actions/settingsActions';
|
||||||
import { fetchStatus } from 'Store/Actions/systemActions';
|
import { fetchStatus } from 'Store/Actions/systemActions';
|
||||||
import { fetchTags } from 'Store/Actions/tagActions';
|
import { fetchTags } from 'Store/Actions/tagActions';
|
||||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||||
@@ -52,7 +52,6 @@ const selectIsPopulated = createSelector(
|
|||||||
(state) => state.indexers.isPopulated,
|
(state) => state.indexers.isPopulated,
|
||||||
(state) => state.indexerStatus.isPopulated,
|
(state) => state.indexerStatus.isPopulated,
|
||||||
(state) => state.settings.indexerCategories.isPopulated,
|
(state) => state.settings.indexerCategories.isPopulated,
|
||||||
(state) => state.settings.indexerFlags.isPopulated,
|
|
||||||
(state) => state.system.status.isPopulated,
|
(state) => state.system.status.isPopulated,
|
||||||
(
|
(
|
||||||
customFiltersIsPopulated,
|
customFiltersIsPopulated,
|
||||||
@@ -63,7 +62,6 @@ const selectIsPopulated = createSelector(
|
|||||||
indexersIsPopulated,
|
indexersIsPopulated,
|
||||||
indexerStatusIsPopulated,
|
indexerStatusIsPopulated,
|
||||||
indexerCategoriesIsPopulated,
|
indexerCategoriesIsPopulated,
|
||||||
indexerFlagsIsPopulated,
|
|
||||||
systemStatusIsPopulated
|
systemStatusIsPopulated
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
@@ -75,7 +73,6 @@ const selectIsPopulated = createSelector(
|
|||||||
indexersIsPopulated &&
|
indexersIsPopulated &&
|
||||||
indexerStatusIsPopulated &&
|
indexerStatusIsPopulated &&
|
||||||
indexerCategoriesIsPopulated &&
|
indexerCategoriesIsPopulated &&
|
||||||
indexerFlagsIsPopulated &&
|
|
||||||
systemStatusIsPopulated
|
systemStatusIsPopulated
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -90,7 +87,6 @@ const selectErrors = createSelector(
|
|||||||
(state) => state.indexers.error,
|
(state) => state.indexers.error,
|
||||||
(state) => state.indexerStatus.error,
|
(state) => state.indexerStatus.error,
|
||||||
(state) => state.settings.indexerCategories.error,
|
(state) => state.settings.indexerCategories.error,
|
||||||
(state) => state.settings.indexerFlags.error,
|
|
||||||
(state) => state.system.status.error,
|
(state) => state.system.status.error,
|
||||||
(
|
(
|
||||||
customFiltersError,
|
customFiltersError,
|
||||||
@@ -101,7 +97,6 @@ const selectErrors = createSelector(
|
|||||||
indexersError,
|
indexersError,
|
||||||
indexerStatusError,
|
indexerStatusError,
|
||||||
indexerCategoriesError,
|
indexerCategoriesError,
|
||||||
indexerFlagsError,
|
|
||||||
systemStatusError
|
systemStatusError
|
||||||
) => {
|
) => {
|
||||||
const hasError = !!(
|
const hasError = !!(
|
||||||
@@ -113,7 +108,6 @@ const selectErrors = createSelector(
|
|||||||
indexersError ||
|
indexersError ||
|
||||||
indexerStatusError ||
|
indexerStatusError ||
|
||||||
indexerCategoriesError ||
|
indexerCategoriesError ||
|
||||||
indexerFlagsError ||
|
|
||||||
systemStatusError
|
systemStatusError
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -127,7 +121,6 @@ const selectErrors = createSelector(
|
|||||||
indexersError,
|
indexersError,
|
||||||
indexerStatusError,
|
indexerStatusError,
|
||||||
indexerCategoriesError,
|
indexerCategoriesError,
|
||||||
indexerFlagsError,
|
|
||||||
systemStatusError
|
systemStatusError
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -178,9 +171,6 @@ function createMapDispatchToProps(dispatch, props) {
|
|||||||
dispatchFetchIndexerCategories() {
|
dispatchFetchIndexerCategories() {
|
||||||
dispatch(fetchIndexerCategories());
|
dispatch(fetchIndexerCategories());
|
||||||
},
|
},
|
||||||
dispatchFetchIndexerFlags() {
|
|
||||||
dispatch(fetchIndexerFlags());
|
|
||||||
},
|
|
||||||
dispatchFetchUISettings() {
|
dispatchFetchUISettings() {
|
||||||
dispatch(fetchUISettings());
|
dispatch(fetchUISettings());
|
||||||
},
|
},
|
||||||
@@ -220,7 +210,6 @@ class PageConnector extends Component {
|
|||||||
this.props.dispatchFetchIndexers();
|
this.props.dispatchFetchIndexers();
|
||||||
this.props.dispatchFetchIndexerStatus();
|
this.props.dispatchFetchIndexerStatus();
|
||||||
this.props.dispatchFetchIndexerCategories();
|
this.props.dispatchFetchIndexerCategories();
|
||||||
this.props.dispatchFetchIndexerFlags();
|
|
||||||
this.props.dispatchFetchUISettings();
|
this.props.dispatchFetchUISettings();
|
||||||
this.props.dispatchFetchGeneralSettings();
|
this.props.dispatchFetchGeneralSettings();
|
||||||
this.props.dispatchFetchStatus();
|
this.props.dispatchFetchStatus();
|
||||||
@@ -246,7 +235,6 @@ class PageConnector extends Component {
|
|||||||
dispatchFetchIndexers,
|
dispatchFetchIndexers,
|
||||||
dispatchFetchIndexerStatus,
|
dispatchFetchIndexerStatus,
|
||||||
dispatchFetchIndexerCategories,
|
dispatchFetchIndexerCategories,
|
||||||
dispatchFetchIndexerFlags,
|
|
||||||
dispatchFetchUISettings,
|
dispatchFetchUISettings,
|
||||||
dispatchFetchGeneralSettings,
|
dispatchFetchGeneralSettings,
|
||||||
dispatchFetchStatus,
|
dispatchFetchStatus,
|
||||||
@@ -287,7 +275,6 @@ PageConnector.propTypes = {
|
|||||||
dispatchFetchIndexers: PropTypes.func.isRequired,
|
dispatchFetchIndexers: PropTypes.func.isRequired,
|
||||||
dispatchFetchIndexerStatus: PropTypes.func.isRequired,
|
dispatchFetchIndexerStatus: PropTypes.func.isRequired,
|
||||||
dispatchFetchIndexerCategories: PropTypes.func.isRequired,
|
dispatchFetchIndexerCategories: PropTypes.func.isRequired,
|
||||||
dispatchFetchIndexerFlags: PropTypes.func.isRequired,
|
|
||||||
dispatchFetchUISettings: PropTypes.func.isRequired,
|
dispatchFetchUISettings: PropTypes.func.isRequired,
|
||||||
dispatchFetchGeneralSettings: PropTypes.func.isRequired,
|
dispatchFetchGeneralSettings: PropTypes.func.isRequired,
|
||||||
dispatchFetchStatus: PropTypes.func.isRequired,
|
dispatchFetchStatus: PropTypes.func.isRequired,
|
||||||
|
@@ -10,6 +10,7 @@ import { icons, kinds, tooltipPositions } from 'Helpers/Props';
|
|||||||
import formatDateTime from 'Utilities/Date/formatDateTime';
|
import formatDateTime from 'Utilities/Date/formatDateTime';
|
||||||
import formatAge from 'Utilities/Number/formatAge';
|
import formatAge from 'Utilities/Number/formatAge';
|
||||||
import formatBytes from 'Utilities/Number/formatBytes';
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
|
import titleCase from 'Utilities/String/titleCase';
|
||||||
import translate from 'Utilities/String/translate';
|
import translate from 'Utilities/String/translate';
|
||||||
import CategoryLabel from './CategoryLabel';
|
import CategoryLabel from './CategoryLabel';
|
||||||
import Peers from './Peers';
|
import Peers from './Peers';
|
||||||
@@ -249,7 +250,7 @@ class SearchIndexRow extends Component {
|
|||||||
indexerFlags.map((flag, index) => {
|
indexerFlags.map((flag, index) => {
|
||||||
return (
|
return (
|
||||||
<li key={index}>
|
<li key={index}>
|
||||||
{flag}
|
{titleCase(flag)}
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@@ -1,48 +0,0 @@
|
|||||||
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
|
||||||
import { createThunk } from 'Store/thunks';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Variables
|
|
||||||
|
|
||||||
const section = 'settings.indexerFlags';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Actions Types
|
|
||||||
|
|
||||||
export const FETCH_INDEXER_FLAGS = 'settings/indexerFlags/fetchIndexerFlags';
|
|
||||||
|
|
||||||
//
|
|
||||||
// Action Creators
|
|
||||||
|
|
||||||
export const fetchIndexerFlags = createThunk(FETCH_INDEXER_FLAGS);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Details
|
|
||||||
|
|
||||||
export default {
|
|
||||||
|
|
||||||
//
|
|
||||||
// State
|
|
||||||
|
|
||||||
defaultState: {
|
|
||||||
isFetching: false,
|
|
||||||
isPopulated: false,
|
|
||||||
error: null,
|
|
||||||
items: []
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// Action Handlers
|
|
||||||
|
|
||||||
actionHandlers: {
|
|
||||||
[FETCH_INDEXER_FLAGS]: createFetchHandler(section, '/indexerFlag')
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// Reducers
|
|
||||||
|
|
||||||
reducers: {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
@@ -6,7 +6,6 @@ import development from './Settings/development';
|
|||||||
import downloadClients from './Settings/downloadClients';
|
import downloadClients from './Settings/downloadClients';
|
||||||
import general from './Settings/general';
|
import general from './Settings/general';
|
||||||
import indexerCategories from './Settings/indexerCategories';
|
import indexerCategories from './Settings/indexerCategories';
|
||||||
import indexerFlags from './Settings/indexerFlags';
|
|
||||||
import languages from './Settings/languages';
|
import languages from './Settings/languages';
|
||||||
import notifications from './Settings/notifications';
|
import notifications from './Settings/notifications';
|
||||||
import ui from './Settings/ui';
|
import ui from './Settings/ui';
|
||||||
@@ -14,7 +13,6 @@ import ui from './Settings/ui';
|
|||||||
export * from './Settings/downloadClients';
|
export * from './Settings/downloadClients';
|
||||||
export * from './Settings/general';
|
export * from './Settings/general';
|
||||||
export * from './Settings/indexerCategories';
|
export * from './Settings/indexerCategories';
|
||||||
export * from './Settings/indexerFlags';
|
|
||||||
export * from './Settings/languages';
|
export * from './Settings/languages';
|
||||||
export * from './Settings/notifications';
|
export * from './Settings/notifications';
|
||||||
export * from './Settings/applications';
|
export * from './Settings/applications';
|
||||||
@@ -35,7 +33,6 @@ export const defaultState = {
|
|||||||
downloadClients: downloadClients.defaultState,
|
downloadClients: downloadClients.defaultState,
|
||||||
general: general.defaultState,
|
general: general.defaultState,
|
||||||
indexerCategories: indexerCategories.defaultState,
|
indexerCategories: indexerCategories.defaultState,
|
||||||
indexerFlags: indexerFlags.defaultState,
|
|
||||||
languages: languages.defaultState,
|
languages: languages.defaultState,
|
||||||
notifications: notifications.defaultState,
|
notifications: notifications.defaultState,
|
||||||
applications: applications.defaultState,
|
applications: applications.defaultState,
|
||||||
@@ -64,7 +61,6 @@ export const actionHandlers = handleThunks({
|
|||||||
...downloadClients.actionHandlers,
|
...downloadClients.actionHandlers,
|
||||||
...general.actionHandlers,
|
...general.actionHandlers,
|
||||||
...indexerCategories.actionHandlers,
|
...indexerCategories.actionHandlers,
|
||||||
...indexerFlags.actionHandlers,
|
|
||||||
...languages.actionHandlers,
|
...languages.actionHandlers,
|
||||||
...notifications.actionHandlers,
|
...notifications.actionHandlers,
|
||||||
...applications.actionHandlers,
|
...applications.actionHandlers,
|
||||||
@@ -84,7 +80,6 @@ export const reducers = createHandleActions({
|
|||||||
...downloadClients.reducers,
|
...downloadClients.reducers,
|
||||||
...general.reducers,
|
...general.reducers,
|
||||||
...indexerCategories.reducers,
|
...indexerCategories.reducers,
|
||||||
...indexerFlags.reducers,
|
|
||||||
...languages.reducers,
|
...languages.reducers,
|
||||||
...notifications.reducers,
|
...notifications.reducers,
|
||||||
...applications.reducers,
|
...applications.reducers,
|
||||||
|
@@ -64,7 +64,7 @@ namespace NzbDrone.Core.Test.IndexerTests.PTPTests
|
|||||||
first.Peers.Should().Be(28);
|
first.Peers.Should().Be(28);
|
||||||
first.Seeders.Should().Be(26);
|
first.Seeders.Should().Be(26);
|
||||||
|
|
||||||
torrents.Any(t => t.IndexerFlags.HasFlag(IndexerFlags.G_Freeleech)).Should().Be(true);
|
torrents.Any(t => t.IndexerFlags.Contains(IndexerFlag.Scene)).Should().Be(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -87,6 +87,7 @@ namespace NzbDrone.Core.IndexerSearch
|
|||||||
r.Size == null ? null : new XAttribute("length", r.Size),
|
r.Size == null ? null : new XAttribute("length", r.Size),
|
||||||
new XAttribute("type", protocol == DownloadProtocol.Torrent ? "application/x-bittorrent" : "application/x-nzb")),
|
new XAttribute("type", protocol == DownloadProtocol.Torrent ? "application/x-bittorrent" : "application/x-nzb")),
|
||||||
r.Category == null ? null : from c in r.Category select GetNabElement("category", c.Id, protocol),
|
r.Category == null ? null : from c in r.Category select GetNabElement("category", c.Id, protocol),
|
||||||
|
r.IndexerFlags == null ? null : from f in r.IndexerFlags select GetNabElement("tag", f.Name, protocol),
|
||||||
GetNabElement("rageid", r.TvRageId, protocol),
|
GetNabElement("rageid", r.TvRageId, protocol),
|
||||||
GetNabElement("thetvdb", r.TvdbId, protocol),
|
GetNabElement("thetvdb", r.TvdbId, protocol),
|
||||||
GetNabElement("imdb", r.ImdbId.ToString("D7"), protocol),
|
GetNabElement("imdb", r.ImdbId.ToString("D7"), protocol),
|
||||||
|
@@ -51,6 +51,10 @@ namespace NzbDrone.Core.Indexers.FileList
|
|||||||
BookSearchParams = new List<BookSearchParam>
|
BookSearchParams = new List<BookSearchParam>
|
||||||
{
|
{
|
||||||
BookSearchParam.Q
|
BookSearchParam.Q
|
||||||
|
},
|
||||||
|
Flags = new List<IndexerFlag>
|
||||||
|
{
|
||||||
|
IndexerFlag.FreeLeech
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -36,11 +36,11 @@ namespace NzbDrone.Core.Indexers.FileList
|
|||||||
{
|
{
|
||||||
var id = result.Id;
|
var id = result.Id;
|
||||||
|
|
||||||
IndexerFlags flags = 0;
|
var flags = new List<IndexerFlag>();
|
||||||
|
|
||||||
if (result.FreeLeech)
|
if (result.FreeLeech)
|
||||||
{
|
{
|
||||||
flags |= IndexerFlags.G_Freeleech;
|
flags.Add(IndexerFlag.FreeLeech);
|
||||||
}
|
}
|
||||||
|
|
||||||
var imdbId = 0;
|
var imdbId = 0;
|
||||||
|
@@ -55,16 +55,16 @@ namespace NzbDrone.Core.Indexers.HDBits
|
|||||||
var id = result.Id;
|
var id = result.Id;
|
||||||
var internalRelease = result.TypeOrigin == 1 ? true : false;
|
var internalRelease = result.TypeOrigin == 1 ? true : false;
|
||||||
|
|
||||||
IndexerFlags flags = 0;
|
var flags = new List<IndexerFlag>();
|
||||||
|
|
||||||
if (result.FreeLeech == "yes")
|
if (result.FreeLeech == "yes")
|
||||||
{
|
{
|
||||||
flags |= IndexerFlags.G_Freeleech;
|
flags.Add(IndexerFlag.FreeLeech);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (internalRelease)
|
if (internalRelease)
|
||||||
{
|
{
|
||||||
flags |= IndexerFlags.HDB_Internal;
|
flags.Add(IndexerFlag.Internal);
|
||||||
}
|
}
|
||||||
|
|
||||||
torrentInfos.Add(new HDBitsInfo()
|
torrentInfos.Add(new HDBitsInfo()
|
||||||
|
@@ -52,6 +52,12 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
|
|||||||
MovieSearchParams = new List<MovieSearchParam>
|
MovieSearchParams = new List<MovieSearchParam>
|
||||||
{
|
{
|
||||||
MovieSearchParam.Q, MovieSearchParam.ImdbId
|
MovieSearchParam.Q, MovieSearchParam.ImdbId
|
||||||
|
},
|
||||||
|
Flags = new List<IndexerFlag>
|
||||||
|
{
|
||||||
|
IndexerFlag.FreeLeech,
|
||||||
|
PassThePopcornFlag.Golden,
|
||||||
|
PassThePopcornFlag.Approved
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -74,7 +80,13 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
|
|||||||
|
|
||||||
public override IParseIndexerResponse GetParser()
|
public override IParseIndexerResponse GetParser()
|
||||||
{
|
{
|
||||||
return new PassThePopcornParser(BaseUrl, _logger);
|
return new PassThePopcornParser(BaseUrl, Capabilities, _logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class PassThePopcornFlag : IndexerFlag
|
||||||
|
{
|
||||||
|
public static IndexerFlag Golden => new IndexerFlag("golden", "Release follows Golden Popcorn quality rules");
|
||||||
|
public static IndexerFlag Approved => new IndexerFlag("approved", "Release approved by PTP");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,10 +13,12 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
|
|||||||
public class PassThePopcornParser : IParseIndexerResponse
|
public class PassThePopcornParser : IParseIndexerResponse
|
||||||
{
|
{
|
||||||
private readonly string _baseUrl;
|
private readonly string _baseUrl;
|
||||||
|
private readonly IndexerCapabilities _capabilities;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
public PassThePopcornParser(string baseUrl, Logger logger)
|
public PassThePopcornParser(string baseUrl, IndexerCapabilities capabilities, Logger logger)
|
||||||
{
|
{
|
||||||
_baseUrl = baseUrl;
|
_baseUrl = baseUrl;
|
||||||
|
_capabilities = capabilities;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,26 +65,27 @@ namespace NzbDrone.Core.Indexers.PassThePopcorn
|
|||||||
{
|
{
|
||||||
var id = torrent.Id;
|
var id = torrent.Id;
|
||||||
var title = torrent.ReleaseName;
|
var title = torrent.ReleaseName;
|
||||||
IndexerFlags flags = 0;
|
|
||||||
|
var flags = new List<IndexerFlag>();
|
||||||
|
|
||||||
if (torrent.GoldenPopcorn)
|
if (torrent.GoldenPopcorn)
|
||||||
{
|
{
|
||||||
flags |= IndexerFlags.PTP_Golden; //title = $"{title} 🍿";
|
flags.Add(PassThePopcornFlag.Golden);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (torrent.Checked)
|
if (torrent.Checked)
|
||||||
{
|
{
|
||||||
flags |= IndexerFlags.PTP_Approved; //title = $"{title} ✔";
|
flags.Add(PassThePopcornFlag.Approved); //title = $"{title} ✔";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (torrent.FreeleechType == "Freeleech")
|
if (torrent.FreeleechType == "Freeleech")
|
||||||
{
|
{
|
||||||
flags |= IndexerFlags.G_Freeleech;
|
flags.Add(IndexerFlag.FreeLeech);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (torrent.Scene)
|
if (torrent.Scene)
|
||||||
{
|
{
|
||||||
flags |= IndexerFlags.G_Scene;
|
flags.Add(IndexerFlag.Scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
var free = !(torrent.FreeleechType is null);
|
var free = !(torrent.FreeleechType is null);
|
||||||
|
@@ -173,9 +173,9 @@ namespace NzbDrone.Core.Indexers.Torznab
|
|||||||
return base.GetPeers(item);
|
return base.GetPeers(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IndexerFlags GetFlags(XElement item)
|
protected List<IndexerFlag> GetFlags(XElement item)
|
||||||
{
|
{
|
||||||
IndexerFlags flags = 0;
|
var flags = new List<IndexerFlag>();
|
||||||
|
|
||||||
var downloadFactor = TryGetFloatTorznabAttribute(item, "downloadvolumefactor", 1);
|
var downloadFactor = TryGetFloatTorznabAttribute(item, "downloadvolumefactor", 1);
|
||||||
|
|
||||||
@@ -183,17 +183,17 @@ namespace NzbDrone.Core.Indexers.Torznab
|
|||||||
|
|
||||||
if (uploadFactor == 2)
|
if (uploadFactor == 2)
|
||||||
{
|
{
|
||||||
flags |= IndexerFlags.G_DoubleUpload;
|
flags.Add(IndexerFlag.DoubleUpload);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downloadFactor == 0.5)
|
if (downloadFactor == 0.5)
|
||||||
{
|
{
|
||||||
flags |= IndexerFlags.G_Halfleech;
|
flags.Add(IndexerFlag.HalfLeech);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downloadFactor == 0.0)
|
if (downloadFactor == 0.0)
|
||||||
{
|
{
|
||||||
flags |= IndexerFlags.G_Freeleech;
|
flags.Add(IndexerFlag.FreeLeech);
|
||||||
}
|
}
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
|
@@ -83,6 +83,7 @@ namespace NzbDrone.Core.Indexers
|
|||||||
public bool BookSearchAuthorAvailable => BookSearchParams.Contains(BookSearchParam.Author);
|
public bool BookSearchAuthorAvailable => BookSearchParams.Contains(BookSearchParam.Author);
|
||||||
|
|
||||||
public readonly IndexerCapabilitiesCategories Categories;
|
public readonly IndexerCapabilitiesCategories Categories;
|
||||||
|
public List<IndexerFlag> Flags;
|
||||||
|
|
||||||
public IndexerCapabilities()
|
public IndexerCapabilities()
|
||||||
{
|
{
|
||||||
@@ -92,6 +93,7 @@ namespace NzbDrone.Core.Indexers
|
|||||||
MusicSearchParams = new List<MusicSearchParam>();
|
MusicSearchParams = new List<MusicSearchParam>();
|
||||||
BookSearchParams = new List<BookSearchParam>();
|
BookSearchParams = new List<BookSearchParam>();
|
||||||
Categories = new IndexerCapabilitiesCategories();
|
Categories = new IndexerCapabilitiesCategories();
|
||||||
|
Flags = new List<IndexerFlag>();
|
||||||
LimitsDefault = 100;
|
LimitsDefault = 100;
|
||||||
LimitsMax = 100;
|
LimitsMax = 100;
|
||||||
}
|
}
|
||||||
@@ -386,7 +388,12 @@ namespace NzbDrone.Core.Indexers
|
|||||||
from sc in c.SubCategories
|
from sc in c.SubCategories
|
||||||
select new XElement("subcat",
|
select new XElement("subcat",
|
||||||
new XAttribute("id", sc.Id),
|
new XAttribute("id", sc.Id),
|
||||||
new XAttribute("name", sc.Name))))));
|
new XAttribute("name", sc.Name)))),
|
||||||
|
new XElement("tags",
|
||||||
|
from c in Flags
|
||||||
|
select new XElement("tag",
|
||||||
|
new XAttribute("name", c.Name),
|
||||||
|
new XAttribute("description", c.Description)))));
|
||||||
return xdoc;
|
return xdoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
75
src/NzbDrone.Core/Indexers/IndexerFlag.cs
Normal file
75
src/NzbDrone.Core/Indexers/IndexerFlag.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Indexers
|
||||||
|
{
|
||||||
|
public class IndexerFlag : IEquatable<IndexerFlag>
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
public IndexerFlag()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexerFlag(string name, string description)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Name.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(IndexerFlag other)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, other))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(this, other))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Name.Equals(other.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(this, obj))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Equals(obj as IndexerFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(IndexerFlag left, IndexerFlag right)
|
||||||
|
{
|
||||||
|
return Equals(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(IndexerFlag left, IndexerFlag right)
|
||||||
|
{
|
||||||
|
return !Equals(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IndexerFlag Internal => new IndexerFlag("internal", "Uploader is an internal release group");
|
||||||
|
public static IndexerFlag FreeLeech => new IndexerFlag("freeleech", "Release doesn't count torward ratio");
|
||||||
|
public static IndexerFlag HalfLeech => new IndexerFlag("halfleech", "Release counts 50% to ratio");
|
||||||
|
public static IndexerFlag Scene => new IndexerFlag("scene", "Uploader follows scene rules");
|
||||||
|
public static IndexerFlag DoubleUpload => new IndexerFlag("doubleupload", "Seeding counts double for release");
|
||||||
|
}
|
||||||
|
}
|
@@ -34,7 +34,7 @@ namespace NzbDrone.Core.Parser.Model
|
|||||||
public string Resolution { get; set; }
|
public string Resolution { get; set; }
|
||||||
public ICollection<IndexerCategory> Category { get; set; }
|
public ICollection<IndexerCategory> Category { get; set; }
|
||||||
|
|
||||||
public IndexerFlags IndexerFlags { get; set; }
|
public ICollection<IndexerFlag> IndexerFlags { get; set; }
|
||||||
|
|
||||||
public int Age
|
public int Age
|
||||||
{
|
{
|
||||||
@@ -134,20 +134,4 @@ namespace NzbDrone.Core.Parser.Model
|
|||||||
|
|
||||||
public static long BytesFromKB(float kb) => (long)(kb * 1024f);
|
public static long BytesFromKB(float kb) => (long)(kb * 1024f);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
|
||||||
public enum IndexerFlags
|
|
||||||
{
|
|
||||||
G_Freeleech = 1, //General
|
|
||||||
G_Halfleech = 2, //General, only 1/2 of download counted
|
|
||||||
G_DoubleUpload = 4, //General
|
|
||||||
PTP_Golden = 8, //PTP
|
|
||||||
PTP_Approved = 16, //PTP
|
|
||||||
HDB_Internal = 32, //HDBits, internal
|
|
||||||
AHD_Internal = 64, // AHD, internal
|
|
||||||
G_Scene = 128, //General, the torrent comes from the "scene"
|
|
||||||
G_Freeleech75 = 256, //Currently only used for AHD, signifies a torrent counts towards 75 percent of your download quota.
|
|
||||||
G_Freeleech25 = 512, //Currently only used for AHD, signifies a torrent counts towards 25 percent of your download quota.
|
|
||||||
AHD_UserRelease = 1024 // AHD, internal
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,23 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using NzbDrone.Core.Parser.Model;
|
|
||||||
using Prowlarr.Http;
|
|
||||||
|
|
||||||
namespace Prowlarr.Api.V1.Indexers
|
|
||||||
{
|
|
||||||
[V1ApiController]
|
|
||||||
public class IndexerFlagController : Controller
|
|
||||||
{
|
|
||||||
[HttpGet]
|
|
||||||
public List<IndexerFlagResource> GetAll()
|
|
||||||
{
|
|
||||||
return Enum.GetValues(typeof(IndexerFlags)).Cast<IndexerFlags>().Select(f => new IndexerFlagResource
|
|
||||||
{
|
|
||||||
Id = (int)f,
|
|
||||||
Name = f.ToString()
|
|
||||||
}).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,13 +0,0 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
using Prowlarr.Http.REST;
|
|
||||||
|
|
||||||
namespace Prowlarr.Api.V1.Indexers
|
|
||||||
{
|
|
||||||
public class IndexerFlagResource : RestResource
|
|
||||||
{
|
|
||||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Include)]
|
|
||||||
public new int Id { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string NameLower => Name.ToLowerInvariant();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -43,7 +43,7 @@ namespace Prowlarr.Api.V1.Search
|
|||||||
{
|
{
|
||||||
var releaseInfo = model;
|
var releaseInfo = model;
|
||||||
var torrentInfo = (model as TorrentInfo) ?? new TorrentInfo();
|
var torrentInfo = (model as TorrentInfo) ?? new TorrentInfo();
|
||||||
var indexerFlags = torrentInfo.IndexerFlags.ToString().Split(new string[] { ", " }, StringSplitOptions.None).Where(x => x != "0");
|
var indexerFlags = torrentInfo.IndexerFlags.Select(f => f.Name);
|
||||||
|
|
||||||
// TODO: Clean this mess up. don't mix data from multiple classes, use sub-resources instead? (Got a huge Deja Vu, didn't we talk about this already once?)
|
// TODO: Clean this mess up. don't mix data from multiple classes, use sub-resources instead? (Got a huge Deja Vu, didn't we talk about this already once?)
|
||||||
return new SearchResource
|
return new SearchResource
|
||||||
|
Reference in New Issue
Block a user