448ed48ebf
- BitMidi is blocked by Cloudflare on Vercel (403) - Dongrays domain is dead (ENOTFOUND) - Add FreeMidi adapter as primary search source - FreeMidi returns real MIDI files without blocking 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
65 lines
1.9 KiB
TypeScript
65 lines
1.9 KiB
TypeScript
import type { SearchAdapter, MIDICandidate } from '../types.js';
|
|
import { BitMidiAdapter } from '../adapters/BitMidiAdapter.js';
|
|
import { FreeMidiAdapter } from '../adapters/FreeMidiAdapter.js';
|
|
|
|
export class MIDISearchService {
|
|
private adapters: SearchAdapter[];
|
|
|
|
constructor() {
|
|
// FreeMidi first (more reliable), BitMidi as backup
|
|
this.adapters = [
|
|
new FreeMidiAdapter(),
|
|
new BitMidiAdapter()
|
|
];
|
|
console.log('MIDISearchService initialized with adapters:', this.adapters.map(a => a.name));
|
|
}
|
|
|
|
async search(query: string): Promise<MIDICandidate[]> {
|
|
const allResults: MIDICandidate[] = [];
|
|
|
|
// Search all adapters in parallel
|
|
const searchPromises = this.adapters.map(async adapter => {
|
|
try {
|
|
const results = await adapter.search(query);
|
|
console.log(`${adapter.name}: Found ${results.length} results`);
|
|
return results;
|
|
} catch (error) {
|
|
console.error(`${adapter.name} search failed:`, error);
|
|
return [];
|
|
}
|
|
});
|
|
|
|
const results = await Promise.all(searchPromises);
|
|
|
|
// Combine and deduplicate results
|
|
for (const adapterResults of results) {
|
|
allResults.push(...adapterResults);
|
|
}
|
|
|
|
// Remove duplicates (same MIDI URL)
|
|
const uniqueResults = this.deduplicateResults(allResults);
|
|
|
|
// Sort by confidence score
|
|
uniqueResults.sort((a, b) => b.confidence - a.confidence);
|
|
|
|
// Return top 10 results
|
|
return uniqueResults.slice(0, 10);
|
|
}
|
|
|
|
private deduplicateResults(results: MIDICandidate[]): MIDICandidate[] {
|
|
const seen = new Set<string>();
|
|
const unique: MIDICandidate[] = [];
|
|
|
|
for (const result of results) {
|
|
// Create dedup key from MIDI URL or title+source
|
|
const key = result.midiUrl || `${result.title}_${result.source}`;
|
|
|
|
if (!seen.has(key)) {
|
|
seen.add(key);
|
|
unique.push(result);
|
|
}
|
|
}
|
|
|
|
return unique;
|
|
}
|
|
} |