Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The Google site has changed, breaking the converter #75

Open
AllyMcSqueal opened this issue Jan 22, 2025 · 5 comments
Open

The Google site has changed, breaking the converter #75

AllyMcSqueal opened this issue Jan 22, 2025 · 5 comments

Comments

@AllyMcSqueal
Copy link

It would appear that the response that's received from Google when querying "https://www.google.com/search?q=${this.currencyAmount}+${this.currencyFrom}+to+${this.currencyTo}+&hl=en" has changed. That results in the converter returning NaN when called with the .convert method.

@artureg
Copy link

artureg commented Jan 23, 2025

Have you found any other working solutions?

@ysrdevs
Copy link

ysrdevs commented Jan 23, 2025

Would be better to target this div instead. Searching 1 USD to 1 CAD it shows the exact conversion rate in code. I'm trying to fix on my end.

<div class="b1hJbf" data-exchange-rate="1.4379549999999999">

@Nneji123
Copy link

Nneji123 commented Feb 1, 2025

If you're using this within a project and don't want to change the code methods much you can use this class instead

const NodeCache = require('node-cache');
const axios = require('axios');

class CurrencyConverter {
  constructor(config = {}) {
    this.apiKey = config.apiKey || process.env.OPENEXCHANGE_API_KEY;
    if (!this.apiKey) {
      throw new Error('OpenExchange API key is required');
    }

    this.baseUrl = 'https://open.exchangerate-api.com/v6';
    this.isDecimalComma = config.isDecimalComma || false;
    this.fromCurrency = null;
    this.toCurrency = null;
    this.amount = null;

    this.cache = new NodeCache();
    this.isRatesCaching = false;
    this.ratesCacheDuration = 3600;
  }

  from(currency) {
    console.log('Setting from currency:', currency);
    this.fromCurrency = currency;
    return this;
  }

  to(currency) {
    console.log('Setting to currency:', currency);
    this.toCurrency = currency;
    return this;
  }

  setAmount(value) {
    // Changed from amount() to setAmount()
    console.log('Setting amount:', value);
    this.amount = value;
    return this;
  }

  async convert(amount = null) {
    if (amount !== null) {
      this.amount = amount;
    }

    if (!this.amount) {
      throw new Error('Amount is required for conversion');
    }

    try {
      const rate = await this.getRates();
      const result = this.amount * rate;
      return this.isDecimalComma ? result.toString().replace('.', ',') : result;
    } catch (error) {
      throw new Error(`Conversion failed: ${error.message}`);
    }
  }

  async getRates() {
    if (!this.fromCurrency || !this.toCurrency) {
      throw new Error('From and To currencies are required');
    }

    const cacheKey = `${this.fromCurrency}-${this.toCurrency}`;

    if (this.isRatesCaching) {
      const cachedRate = this.cache.get(cacheKey);
      if (cachedRate) {
        return cachedRate;
      }
    }

    try {
      const response = await axios.get(
        `${this.baseUrl}/latest/${this.fromCurrency}`,
        {
          params: {
            app_id: this.apiKey
          }
        }
      );

      if (!response.data || !response.data.rates) {
        throw new Error('Invalid response from exchange rate API');
      }

      const rate = response.data.rates[this.toCurrency];

      if (!rate) {
        throw new Error(`Rate not found for ${this.toCurrency}`);
      }

      if (this.isRatesCaching) {
        this.cache.set(cacheKey, rate, this.ratesCacheDuration);
      }

      return rate;
    } catch (error) {
      throw new Error(`Failed to fetch exchange rates: ${error.message}`);
    }
  }

  setupRatesCache(options = {}) {
    this.isRatesCaching = options.isRatesCaching || false;
    this.ratesCacheDuration = options.ratesCacheDuration || 3600;
    return this;
  }
}

module.exports = CurrencyConverter;

The only method that's changed is the amount method which was changed to setAmount.

Here's how I use it in a script:

require('dotenv').config();
const CurrencyConverter = require('./src/utils/currencyConverter');

async function testConverter() {
  try {
    console.log('Creating converter instance...');
    const converter = new CurrencyConverter();

    console.log('Setting up cache...');
    converter.setupRatesCache({
      isRatesCaching: true,
      ratesCacheDuration: 3600
    });

    console.log('Starting conversion...');
    const result = await converter
      .from('NGN')
      .to('USD')
      .setAmount(50000) // Note the change here from .amount to .setAmount
      .convert();

    console.log('Conversion result:', result);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

// Run the tests
testConverter();

Make sure to set the OPENEXCHANGE_API_KEY in your .env file or as an environment variable.

@ysrdevs
Copy link

ysrdevs commented Feb 1, 2025

Ended up setting up a new API on my own server. You guys should try it's not that hard to setup. I have a few endpoints and parameters now.

@paul-shuvo
Copy link
Owner

I tested multiple libraries, but it looks like Google isn’t returning any search results when queried through this one. Using tools like puppeteer might work, but it feels like overkill.

Would be better to target this div instead. Searching 1 USD to 1 CAD it shows the exact conversion rate in code. I'm trying to fix on my end.

<div class="b1hJbf" data-exchange-rate="1.4379549999999999">

@ysrdevs are you getting any Google response?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants