140 lines
5.2 KiB
JavaScript
140 lines
5.2 KiB
JavaScript
import {
|
|
firstValidSha256,
|
|
getSha256Candidates,
|
|
getSha256Field,
|
|
normalizeSha256,
|
|
} from '../utils/hash_utils.js';
|
|
import { normalizeSourceKey } from '../utils/source_labels.js';
|
|
|
|
export const searchHashMethods = {
|
|
getSearchResultSha256(result = {}) {
|
|
if (!result || typeof result !== 'object') return '';
|
|
|
|
const fileInfo = result.file_info && typeof result.file_info === 'object' ? result.file_info : {};
|
|
return firstValidSha256(
|
|
result.hash_verified_sha256,
|
|
...getSha256Candidates(result),
|
|
...getSha256Candidates(fileInfo),
|
|
);
|
|
},
|
|
|
|
collectHashLabelMapHashes(missing = {}, results = null) {
|
|
const hashes = [];
|
|
const seen = new Set();
|
|
const addHash = (value) => {
|
|
const hash = normalizeSha256(value);
|
|
if (!hash || !/^[a-f0-9]{64}$/.test(hash) || seen.has(hash)) return;
|
|
seen.add(hash);
|
|
hashes.push(hash);
|
|
};
|
|
const addMatch = (match) => {
|
|
if (!match || typeof match !== 'object') return;
|
|
if (!(match.hash_match || match.match_type === 'hash' || match.hash_lookup_source)) return;
|
|
addHash(this.getLocalMatchHash?.(match) || match.sha256 || match.hash);
|
|
};
|
|
const addResult = (result) => {
|
|
if (Array.isArray(result)) {
|
|
result.forEach(addResult);
|
|
return;
|
|
}
|
|
if (!result || typeof result !== 'object') return;
|
|
const matchType = String(result.match_type || '').toLowerCase();
|
|
if (!(result.hash_verified || result.hash_verified_sha256 || matchType === 'hash')) return;
|
|
addHash(this.getSearchResultSha256?.(result) || result.sha256 || result.hash);
|
|
};
|
|
|
|
(Array.isArray(missing.matches) ? missing.matches : []).forEach(addMatch);
|
|
|
|
const stateResults = results
|
|
|| this.getSearchState?.(missing)?.results
|
|
|| this.searchResultCache?.get?.(this.getMissingSearchKey?.(missing))?.results
|
|
|| {};
|
|
(Array.isArray(stateResults.local_hash_matches) ? stateResults.local_hash_matches : []).forEach(addMatch);
|
|
|
|
[
|
|
missing.download_source,
|
|
stateResults.popular,
|
|
stateResults.model_list,
|
|
stateResults.huggingface,
|
|
stateResults.civitai,
|
|
stateResults.civarchive,
|
|
stateResults.lora_manager_archive,
|
|
...(Array.isArray(stateResults.custom) ? stateResults.custom : [])
|
|
].forEach(addResult);
|
|
|
|
return hashes;
|
|
},
|
|
|
|
getHashMatchLabelMap(missing = {}, results = null) {
|
|
const hashes = this.collectHashLabelMapHashes?.(missing, results) || [];
|
|
const labelMap = new Map();
|
|
if (!hashes.length) return labelMap;
|
|
|
|
const useNumbers = hashes.length > 1;
|
|
hashes.forEach((hash, index) => {
|
|
labelMap.set(hash, useNumbers ? `Hash ${index + 1}` : 'Hash');
|
|
});
|
|
return labelMap;
|
|
},
|
|
|
|
getHashMatchLabelForSearchResult(result = {}, hashLabelMap = null, identities = []) {
|
|
const hash = this.getSearchResultSha256?.(result) || '';
|
|
const label = hash && hashLabelMap?.get?.(hash) ? hashLabelMap.get(hash) : '';
|
|
if (!label) return '';
|
|
|
|
const matchType = String(result.match_type || '').toLowerCase();
|
|
const hasLinkedLocalMatch = Array.isArray(identities) && identities.length > 0;
|
|
return (hasLinkedLocalMatch || result.hash_verified || result.hash_verified_sha256 || matchType === 'hash')
|
|
? label
|
|
: '';
|
|
},
|
|
|
|
getLocalHashMatchIdentitiesForResult(hashMatches = [], sourceKey = '', sourceResult = {}) {
|
|
const identities = [];
|
|
const seen = new Set();
|
|
const addIdentity = (identity) => {
|
|
const normalized = String(identity || '').trim();
|
|
if (!normalized || seen.has(normalized)) return;
|
|
seen.add(normalized);
|
|
identities.push(normalized);
|
|
};
|
|
|
|
if (Array.isArray(sourceResult?.hash_verified_local_match_identities)) {
|
|
sourceResult.hash_verified_local_match_identities.forEach(addIdentity);
|
|
}
|
|
|
|
const normalizedSource = normalizeSourceKey(sourceKey);
|
|
const sourceHash = this.getSearchResultSha256(sourceResult);
|
|
if (!Array.isArray(hashMatches) || !hashMatches.length || !normalizedSource) {
|
|
return identities;
|
|
}
|
|
|
|
hashMatches.forEach(match => {
|
|
if (!match || typeof match !== 'object') return;
|
|
|
|
const matchSource = normalizeSourceKey(match.hash_lookup_source || '');
|
|
const matchHash = normalizeSha256(this.getLocalMatchHash(match));
|
|
if (sourceHash) {
|
|
if (matchHash !== sourceHash) return;
|
|
} else if (!matchSource || matchSource !== normalizedSource) {
|
|
return;
|
|
}
|
|
|
|
addIdentity(this.getLocalMatchIdentity?.(match) || '');
|
|
});
|
|
|
|
return identities;
|
|
},
|
|
|
|
getLocalMatchHash(match = {}) {
|
|
const model = match.model || {};
|
|
const modelHash = getSha256Field(model);
|
|
return String(
|
|
match.sha256
|
|
|| match.hash
|
|
|| modelHash
|
|
|| ''
|
|
).trim();
|
|
},
|
|
};
|