Skip to content

Commit d209ff9

Browse files
fix: jellyseer won't connect and toast notification function restored [skip bump]
2 parents 19672a6 + 5f0d4e4 commit d209ff9

2 files changed

Lines changed: 61 additions & 27 deletions

File tree

api_service/blueprints/seer/routes.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,20 @@ def _load_seer_config():
2929
@seer_bp.route('/get_users', methods=['GET', 'POST'])
3030
async def get_users():
3131
"""
32-
Fetch Jellyseer/Overseer users using the globally configured API key.
32+
Fetch Jellyseer/Overseer users using the globally configured API key and URL,
33+
or credentials provided in the request body (e.g. during initial setup).
3334
"""
3435
try:
3536
config_data = request.get_json(silent=True) or {}
3637
api_url = config_data.get('SEER_API_URL')
3738
api_key = config_data.get('SEER_TOKEN')
3839
session_token = config_data.get('SEER_SESSION_TOKEN')
3940

41+
# Fallback to database config if not provided in request
4042
if not api_url or not api_key:
41-
api_url, api_key, session_token = _load_seer_config()
43+
api_url, api_key, db_session_token = _load_seer_config()
44+
if not session_token:
45+
session_token = db_session_token
4246

4347
if not api_key or not api_url:
4448
return jsonify({'message': 'Seer API URL and token are not configured', 'type': 'error'}), 400

client/src/components/settings/SettingsServices.vue

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -860,25 +860,36 @@ export default {
860860
this._runAutoTests();
861861
},
862862
methods: {
863+
_notifyError(message, opts = { position: 'top-right', duration: 5000 }) {
864+
if (this.$toast) {
865+
this.$toast.error(message, opts);
866+
return;
867+
}
868+
if (this.wizardMode && typeof window !== 'undefined' && typeof window.alert === 'function') {
869+
window.alert(message);
870+
}
871+
},
872+
863873
// Runs all silent connection tests in parallel on mount so they don't block each other.
864874
_runAutoTests() {
865875
const service = this.localConfig.SELECTED_SERVICE;
866876
const tasks = [];
877+
const silent = !this.wizardMode;
867878
868879
if (service === 'plex' && this.localConfig.PLEX_TOKEN && this.localConfig.PLEX_API_URL) {
869880
tasks.push(
870-
this.testAndFetchPlex(true).then(() => {
881+
this.testAndFetchPlex(silent).then(() => {
871882
if (this.plexConnected) this.plexOAuthLoggedIn = true;
872883
}),
873884
);
874885
} else if ((service === 'jellyfin' || service === 'emby') &&
875886
this.localConfig.JELLYFIN_TOKEN && this.localConfig.JELLYFIN_API_URL) {
876-
tasks.push(this.testAndFetchJellyfin(true));
887+
tasks.push(this.testAndFetchJellyfin(silent));
877888
}
878889
879890
if (this.localConfig.SEER_API_URL && this.localConfig.SEER_TOKEN) {
880891
tasks.push(
881-
this.testSeerAndFetchUsers(true).then(async () => {
892+
this.testSeerAndFetchUsers(silent).then(async () => {
882893
if (this.seerConnected && this.localConfig.SEER_SESSION_TOKEN) {
883894
await this.fetchArrServers();
884895
}
@@ -887,7 +898,7 @@ export default {
887898
}
888899
889900
if (this.localConfig.OMDB_API_KEY) {
890-
tasks.push(this.testOmdbConnection(true));
901+
tasks.push(this.testOmdbConnection(silent));
891902
}
892903
893904
Promise.allSettled(tasks);
@@ -909,7 +920,7 @@ export default {
909920
window.open(auth_url, '_blank', 'width=800,height=600');
910921
this.plexOAuthPollTimer = setInterval(() => this.pollPlexOAuth(pin_id), 3000);
911922
} catch {
912-
this.$toast.error('Error starting Plex login.');
923+
this._notifyError('Error starting Plex login.');
913924
this.plexOAuthLoading = false;
914925
}
915926
},
@@ -940,7 +951,7 @@ export default {
940951
await this.onPlexOAuthServerSelect(url);
941952
}
942953
} catch {
943-
this.$toast.error('Error fetching Plex servers.');
954+
this._notifyError('Error fetching Plex servers.');
944955
}
945956
},
946957
async onPlexOAuthServerSelect(url) {
@@ -998,7 +1009,7 @@ export default {
9981009
this.$emit('validation-changed', true);
9991010
} catch (error) {
10001011
this.wizardTmdbConnected = false;
1001-
if (this.$toast) this.$toast.error('Invalid TMDB API key. Please check and try again.', { position: 'top-right', duration: 5000 });
1012+
this._notifyError('Invalid TMDB API key. Please check and try again.');
10021013
this.$emit('validation-changed', false);
10031014
} finally {
10041015
this.wizardTmdbTesting = false;
@@ -1020,7 +1031,7 @@ export default {
10201031
if (!silent && this.$toast) this.$toast.success('OMDb API key validated!', { position: 'top-right', duration: 3000 });
10211032
} catch (error) {
10221033
this.omdbConnected = false;
1023-
if (!silent && this.$toast) this.$toast.error('Invalid OMDb API key. Please check and try again.', { position: 'top-right', duration: 5000 });
1034+
if (!silent) this._notifyError('Invalid OMDb API key. Please check and try again.');
10241035
} finally {
10251036
this.omdbTesting = false;
10261037
}
@@ -1033,7 +1044,7 @@ export default {
10331044
const testUrl = url.startsWith('http') ? url : `http://${url}`;
10341045
new URL(testUrl);
10351046
} catch (e) {
1036-
if (this.$toast) this.$toast.error('Invalid URL format.', { position: 'top-right', duration: 4000 });
1047+
this._notifyError('Invalid URL format.', { position: 'top-right', duration: 4000 });
10371048
return;
10381049
}
10391050
await this.$emit('test-connection', 'jellyfin', {
@@ -1049,7 +1060,7 @@ export default {
10491060
const testUrl = url.startsWith('http') ? url : `http://${url}`;
10501061
new URL(testUrl);
10511062
} catch (e) {
1052-
if (this.$toast) this.$toast.error('Invalid URL format.', { position: 'top-right', duration: 4000 });
1063+
this._notifyError('Invalid URL format.', { position: 'top-right', duration: 4000 });
10531064
return;
10541065
}
10551066
await this.$emit('test-connection', 'plex', {
@@ -1064,7 +1075,7 @@ export default {
10641075
const url = this.localConfig.JELLYFIN_API_URL.trim();
10651076
new URL(url.startsWith('http') ? url : `http://${url}`);
10661077
} catch (e) {
1067-
if (!silent && this.$toast) this.$toast.error('Invalid URL format.', { position: 'top-right', duration: 4000 });
1078+
if (!silent) this._notifyError('Invalid URL format.', { position: 'top-right', duration: 4000 });
10681079
return;
10691080
}
10701081
this.jellyfinFetching = true;
@@ -1090,7 +1101,7 @@ export default {
10901101
this.jellyfinConnected = false;
10911102
this.jellyfinLibraries = [];
10921103
this.jellyfinUsers = [];
1093-
if (!silent && this.$toast) this.$toast.error('Failed to connect. Check your URL and token.', { position: 'top-right', duration: 5000 });
1104+
if (!silent) this._notifyError('Failed to connect. Check your URL and token.');
10941105
} finally {
10951106
this.jellyfinFetching = false;
10961107
}
@@ -1102,7 +1113,7 @@ export default {
11021113
const url = this.localConfig.PLEX_API_URL.trim();
11031114
new URL(url.startsWith('http') ? url : `http://${url}`);
11041115
} catch (e) {
1105-
if (!silent && this.$toast) this.$toast.error('Invalid URL format.', { position: 'top-right', duration: 4000 });
1116+
if (!silent) this._notifyError('Invalid URL format.', { position: 'top-right', duration: 4000 });
11061117
return;
11071118
}
11081119
this.plexFetching = true;
@@ -1129,7 +1140,7 @@ export default {
11291140
this.plexConnected = false;
11301141
this.plexLibraries = [];
11311142
this.plexUsers = [];
1132-
if (!silent && this.$toast) this.$toast.error('Failed to connect. Check your URL and token.', { position: 'top-right', duration: 5000 });
1143+
if (!silent) this._notifyError('Failed to connect. Check your URL and token.');
11331144
} finally {
11341145
this.plexFetching = false;
11351146
}
@@ -1217,31 +1228,50 @@ export default {
12171228
12181229
// Seer connection test + user fetch
12191230
async testSeerAndFetchUsers(silent = false) {
1220-
if (!this.localConfig.SEER_API_URL || !this.localConfig.SEER_TOKEN) return;
1231+
let seerUrl = (this.localConfig.SEER_API_URL || '').trim();
1232+
let seerToken = (this.localConfig.SEER_TOKEN || '').trim();
1233+
1234+
// Browser autofill can populate password inputs without updating v-model.
1235+
// Read from DOM as a fallback so test requests still include the token.
1236+
if (!seerUrl) {
1237+
const domUrl = (document.getElementById('seerApiUrl')?.value || '').trim();
1238+
if (domUrl) {
1239+
seerUrl = domUrl;
1240+
this.localConfig.SEER_API_URL = domUrl;
1241+
}
1242+
}
1243+
if (!seerToken) {
1244+
const domToken = (document.getElementById('seerToken')?.value || '').trim();
1245+
if (domToken) {
1246+
seerToken = domToken;
1247+
this.localConfig.SEER_TOKEN = domToken;
1248+
}
1249+
}
1250+
1251+
if (!seerUrl || !seerToken) return;
12211252
try {
1222-
const url = this.localConfig.SEER_API_URL.trim();
1253+
const url = seerUrl;
12231254
new URL(url.startsWith('http') ? url : `http://${url}`);
12241255
} catch (e) {
1225-
if (!silent && this.$toast) this.$toast.error('Invalid URL format.', { position: 'top-right', duration: 4000 });
1256+
if (!silent) this._notifyError('Invalid URL format.', { position: 'top-right', duration: 4000 });
12261257
return;
12271258
}
12281259
this.seerTesting = true;
12291260
this.seerConnected = false;
12301261
this.seerUsers = [];
12311262
try {
1232-
const payload = {
1233-
SEER_API_URL: this.localConfig.SEER_API_URL.trim(),
1234-
SEER_TOKEN: this.localConfig.SEER_TOKEN.trim()
1235-
};
1236-
const response = await testJellyseerApi(payload);
1263+
const response = await testJellyseerApi({
1264+
SEER_API_URL: seerUrl,
1265+
SEER_TOKEN: seerToken,
1266+
});
12371267
this.seerUsers = (response.data.users || []).filter(user => user.isLocal);
12381268
this.seerConnected = true;
12391269
this.loadSavedSeerUser();
12401270
if (!silent && this.$toast) this.$toast.success(`Connected! Found ${this.seerUsers.length} local user(s).`, { position: 'top-right', duration: 3000 });
12411271
} catch (error) {
12421272
console.error('Seer connection test failed:', error);
12431273
this.seerConnected = false;
1244-
if (!silent && this.$toast) this.$toast.error('Failed to connect. Verify URL and API Key.', { position: 'top-right', duration: 5000 });
1274+
if (!silent) this._notifyError('Failed to connect. Verify URL and API Key.');
12451275
} finally {
12461276
this.seerTesting = false;
12471277
}
@@ -1261,7 +1291,7 @@ export default {
12611291
} catch (error) {
12621292
console.error('Authentication error:', error);
12631293
this.seerAuthenticated = false;
1264-
if (this.$toast) this.$toast.error('Incorrect username or password', { position: 'top-right', duration: 5000 });
1294+
this._notifyError('Incorrect username or password');
12651295
} finally {
12661296
this.seerAuthenticating = false;
12671297
}
@@ -1293,7 +1323,7 @@ export default {
12931323
console.error('Error fetching Radarr/Sonarr servers:', error);
12941324
this.radarrServers = [];
12951325
this.sonarrServers = [];
1296-
if (this.$toast) this.$toast.error('Failed to fetch servers.', { position: 'top-right', duration: 5000 });
1326+
this._notifyError('Failed to fetch servers.');
12971327
} finally {
12981328
this.loadingServers = false;
12991329
this.serversLoaded = true;

0 commit comments

Comments
 (0)