void UltimateLyricsProvider::lyricsFetched()
{
    NetworkJob *reply = qobject_cast<NetworkJob*>(sender());
    if (!reply) {
        return;
    }

    int id = requests.take(reply);
    reply->deleteLater();
    Song song=songs.take(id);

    if (!reply->ok()) {
        //emit Finished(id);
        emit lyricsReady(id, QString());
        return;
    }

    const QTextCodec *codec = QTextCodec::codecForName(charset.toLatin1().constData());
    const QString originalContent = codec->toUnicode(reply->readAll()).replace("<br />", "<br/>");

    DBUG << name << "response" << originalContent;
    // Check for invalid indicators
    for (const QString &indicator: invalidIndicators) {
        if (originalContent.contains(indicator)) {
            //emit Finished(id);
            DBUG << name << "invalid";
            emit lyricsReady(id, QString());
            return;
        }
    }

    QString lyrics;

    // Apply extract rules
    for (const Rule& rule: extractRules) {
        QString content = originalContent;
        applyExtractRule(rule, content, song);
        #ifndef Q_OS_WIN
        content.replace(QLatin1String("\r"), QLatin1String(""));
        #endif
        content=content.trimmed();

        if (!content.isEmpty()) {
            lyrics = content;
            break;
        }
    }

    // Apply exclude rules
    for (const Rule& rule: excludeRules) {
        applyExcludeRule(rule, lyrics, song);
    }

    lyrics=lyrics.trimmed();
    lyrics.replace("<br/>\n", "<br/>");
    lyrics.replace("<br>\n", "<br/>");
    DBUG << name << (lyrics.isEmpty() ? "empty" : "succeeded");
    emit lyricsReady(id, lyrics);
}
 // Apply exclude rules
 foreach (const Rule& rule, excludeRules) {
     applyExcludeRule(rule, lyrics, song);
 }