NZB Hunt is Huntarr's integrated usenet download client. No external host, port, or API keys needed —
it uses the usenet servers configured in NZB Hunt → Settings → Servers.
` : ''}
Enable or disable this download client
${!isNzbHunt ? `
A friendly name to identify this client
` : ''}
Hostname or IP address of your download client
Port number for your download client (SABnzbd default: 8080, NZBGet default: 6789)
API key from your download client settings. ${isEdit ? 'Leave blank to keep existing.' : ''}
Username for basic authentication (NZBGet typically requires this)
${isEdit ? 'Leave blank to keep existing password' : 'Password for authentication (if required)'}
${!isNzbHunt ? `
Additional Configurations
Adding a category specific to ${isTvContext ? 'TV' : 'Movie'} Hunt avoids conflicts with unrelated downloads. Using a category is optional, but strongly recommended.
` : ''}
Priority to use when grabbing movies that aired within the last 21 days.
Priority to use when grabbing movies that aired over 21 days ago.
Download Client Priority from 1 (Highest) to 99 (Lowest). Default: 50. Round-Robin is used for clients with the same priority.
`;
};
Forms.saveClientFromEditor = function() {
if (!this._currentEditing || this._currentEditing.appType !== 'client') return;
const nameEl = document.getElementById('editor-client-name');
const hostEl = document.getElementById('editor-client-host');
const portEl = document.getElementById('editor-client-port');
const enabledEl = document.getElementById('editor-client-enabled');
const apiKeyEl = document.getElementById('editor-client-apikey');
const usernameEl = document.getElementById('editor-client-username');
const passwordEl = document.getElementById('editor-client-password');
const categoryEl = document.getElementById('editor-client-category');
const recentPriorityEl = document.getElementById('editor-client-recent-priority');
const olderPriorityEl = document.getElementById('editor-client-older-priority');
const clientPriorityEl = document.getElementById('editor-client-priority');
const type = (this._currentEditing && this._currentEditing.originalInstance && this._currentEditing.originalInstance.type)
? String(this._currentEditing.originalInstance.type).trim().toLowerCase()
: 'nzbget';
const isNzbHuntType = (type === 'nzbhunt' || type === 'nzb_hunt');
const name = isNzbHuntType ? 'NZB Hunt' : (nameEl ? nameEl.value.trim() : '');
const host = hostEl ? hostEl.value.trim() : '';
const portDefault = type === 'nzbget' ? 6789 : 8080;
let port = portDefault;
if (portEl && portEl.value.trim() !== '') {
const p = parseInt(portEl.value, 10);
if (!isNaN(p)) port = p;
}
const enabled = enabledEl ? enabledEl.value === 'true' : true;
const apiKey = apiKeyEl ? apiKeyEl.value.trim() : '';
const username = usernameEl ? usernameEl.value.trim() : '';
const password = passwordEl ? passwordEl.value.trim() : '';
const isTvMode = !!(window._mediaHuntInstanceEditorMode === 'tv');
const defaultCategory = isTvMode ? 'tv' : 'movies';
let category = (categoryEl && !isNzbHuntType) ? categoryEl.value.trim() : defaultCategory;
if (isNzbHuntType) {
const orig = this._currentEditing && this._currentEditing.originalInstance;
category = (orig && orig.category) ? String(orig.category).trim() : '';
}
const recentPriority = recentPriorityEl ? (recentPriorityEl.value || 'default').toLowerCase() : 'default';
const olderPriority = olderPriorityEl ? (olderPriorityEl.value || 'default').toLowerCase() : 'default';
let clientPriority = 50;
if (clientPriorityEl && clientPriorityEl.value.trim() !== '') {
const p = parseInt(clientPriorityEl.value, 10);
if (!isNaN(p) && p >= 1 && p <= 99) clientPriority = p;
}
const body = {
name: isNzbHuntType ? 'NZB Hunt' : (name || 'Unnamed'),
type: type,
host: isNzbHuntType ? 'internal' : host,
port: isNzbHuntType ? 0 : port,
enabled: enabled,
category: category || defaultCategory,
recent_priority: recentPriority,
older_priority: olderPriority,
client_priority: clientPriority
};
if (!isNzbHuntType) {
if (apiKey) body.api_key = apiKey;
if (username) body.username = username;
if (password) body.password = password;
}
const isAdd = this._currentEditing.isAdd;
const index = this._currentEditing.index;
const url = isAdd ? './api/clients' : './api/clients/' + index;
const method = isAdd ? 'POST' : 'PUT';
fetch(url, { method: method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })
.then(function(r) {
return r.json().then(function(data) { return { ok: r.ok, data: data }; });
})
.then(function(result) {
if (!result.ok) {
var msg = (result.data && result.data.error) ? result.data.error : 'Save failed';
if (window.huntarrUI && window.huntarrUI.showNotification) {
window.huntarrUI.showNotification(msg, 'error');
}
return;
}
var data = result.data;
if (window.SettingsForms && window.SettingsForms.refreshClientsList) {
window.SettingsForms.refreshClientsList();
}
// Refresh NZB Hunt sidebar group visibility (may have added/removed NZB Hunt client)
if (window.huntarrUI && typeof window.huntarrUI._refreshNzbHuntSidebarGroup === 'function') {
window.huntarrUI._refreshNzbHuntSidebarGroup();
}
if (window.huntarrUI && window.huntarrUI.showNotification) {
window.huntarrUI.showNotification(isAdd ? 'Client added.' : 'Client updated.', 'success');
}
// Don't auto-navigate back to collection after saving a client.
// The user may want to add more clients. The wizard banner on the
// clients page handles the "continue" flow when the user is ready.
if (window.SettingsForms && window.SettingsForms._currentEditing) {
window.SettingsForms._currentEditing.isAdd = false;
if (data && data.index !== undefined) {
window.SettingsForms._currentEditing.index = data.index;
} else if (!isAdd) {
window.SettingsForms._currentEditing.index = index;
}
}
})
.catch(function(err) {
if (window.huntarrUI && window.huntarrUI.showNotification) {
window.huntarrUI.showNotification(err.message || 'Failed to save client', 'error');
}
});
};
Forms.checkClientConnection = function() {
const container = document.getElementById('client-connection-status-container');
const hostEl = document.getElementById('editor-client-host');
const portEl = document.getElementById('editor-client-port');
const apiKeyEl = document.getElementById('editor-client-apikey');
const usernameEl = document.getElementById('editor-client-username');
const passwordEl = document.getElementById('editor-client-password');
if (!container) return;
container.style.display = 'flex';
container.style.justifyContent = 'flex-end';
// Get client type
const type = (this._currentEditing && this._currentEditing.originalInstance && this._currentEditing.originalInstance.type)
? String(this._currentEditing.originalInstance.type).trim().toLowerCase()
: 'nzbget';
// NZB Hunt (built-in) - no connection status; it's built-in and managed in NZB Hunt Settings
if (type === 'nzbhunt' || type === 'nzb_hunt') {
if (container) container.style.display = 'none';
return;
}
const host = hostEl ? hostEl.value.trim() : '';
const port = portEl ? portEl.value.trim() : '';
const apiKey = apiKeyEl ? apiKeyEl.value.trim() : '';
const username = usernameEl ? usernameEl.value.trim() : '';
const password = passwordEl ? passwordEl.value.trim() : '';
// Check if minimum requirements are met
if (!host || !port) {
container.innerHTML = 'Enter host and port';
return;
}
// Show checking status
container.innerHTML = 'Checking...';
// Test connection
fetch('./api/clients/test-connection', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: type,
host: host,
port: parseInt(port, 10) || 8080,
api_key: apiKey,
username: username,
password: password
})
})
.then(function(r) { return r.json().then(function(data) { return { ok: r.ok, data: data }; }); })
.then(function(result) {
const data = result.data || {};
if (data.success === true) {
container.innerHTML = 'Connected';
} else {
container.innerHTML = '' + (data.message || data.error || 'Connection failed') + '';
}
})
.catch(function(err) {
container.innerHTML = '' + (err.message || 'Connection failed') + '';
});
};
})();