Replacing goo.gl links

goo.gl is shutting down (see Google URL Shortener links will no longer be available - Google Developers Blog). So links on your forum that include goo.gl links will be broken after August 25th, 2025.

I developed this script for a client. It took much, much longer than I billed him for and longer than I care to admit.

It finds all of the posts that contain goo.gl and then (if they aren’t maps.app.goo.gl or maps.goo.gl) attempts to replace them with the URL that goo.gl returns. It uses the post revisor, so you can see that it was updated and why and you can revert it if you want. I have tried to make it as failsafe as possible, but use at your own risk.

If you don’t know how to run this script, you probably should not do it yourself. If you need help making it work and have a budget, contact me or ask in Marketplace.

If you use it and have suggestions for how to make it better, you please reply and/or edit it as you see fit.

URL_CACHE ||= {}

def resolve_url_simple(short_url)
  uri = URI.parse(short_url)
  response = Net::HTTP.get_response(uri)
  if response.is_a?(Net::HTTPRedirection)
    response['location']
  else
    short_url # Return original if no redirection
  end
rescue
  short_url # Return original if there was an error
end

def resolve_url(short_url)
  short_url.gsub!(/http:/,"https:")
  # Check if the URL is already in the cache
  return URL_CACHE[short_url] if URL_CACHE.key?(short_url)

  begin
    uri = URI.parse(short_url + "?si=1")
    response = Net::HTTP.get_response(uri)

    # Resolve the URL if it's a redirection
    resolved_url = if response.is_a?(Net::HTTPRedirection)
                     response['location']
                   else
                     short_url # Return original if no redirection
                   end
    sleep 1
    # Store the resolved URL in the cache
    URL_CACHE[short_url] = resolved_url

    resolved_url
  rescue
    # Store the original URL in the cache in case of an error
    URL_CACHE[short_url] = short_url
    short_url
  end
end

def replace_goo_gl_links(text)
  goo_gl_regex = %r{(?<=^|[\[\]\(\)\s])(https?://)?goo\.gl(/[a-zA-Z0-9]+)+}
  text.gsub(goo_gl_regex) do |match|
    if match.include?('maps.app.goo.gl')
      match
    else
      full_url = match.start_with?('http') ? match : "https://#{match}"
      print "FIXING!!: #{match} -----> "
      fixed = resolve_url(full_url)
      puts fixed
      fixed
    end
  end
end

def replace_all_goo_gl_links
  system_user= User.find(-1)
  goo_go = Post.where("raw LIKE '%goo.gl%'")
  total_posts = goo_go.count
  puts "Found #{total_posts} posts to check"
  count = 0
  goo_go.find_each do |post|
    count += 1
    # puts "Processing #{count}. #{Discourse.base_url}/t/#{post.topic_id}/#{post.post_number}"
    print "."
    # for reasons unclear, trying to update posts in these topics crashed rails
    # next if [145478,64885,84408].include? post.topic_id
    # find goo.gl links and the the URL to see what it redirects to
    new_raw = replace_goo_gl_links(post.raw)
    if new_raw != post.raw
      revision_options = {
        edit_reason: "Fix goo.gl links",
        bypass_bump: true
      }
      begin
        puts "Revising (#{count}/#{total_posts}) #{Discourse.base_url}/t/#{post.topic_id}/#{post.post_number}"
        if !post.topic # posts in delted topics have no topic and break PostRevisor
           post.topic = Topic.with_deleted.find_by(id: post.topic_id)
           next if !post.topic
        end
        PostRevisor.new(post).revise!(system_user, raw: new_raw, **revision_options)
      rescue => e
        puts "cannot revise (number: #{count} #{Discourse.base_url}/t/#{post.topic_id}/#{post.post_number}): #{e}"
      end
      sleep 15
    end
  end
end

4 Likes

Why exclude those? These links won’t break?

And thanks for this script. I returned posts that contain these shortened links on my forums, and there are a bunch that will need to be fixed then. :+1:

1 Like

Here’s what Google Maps is generating today: https://maps.app.goo.gl/Qz14oUZQv9aHCCfg6. I decided to guess that those domains they have decided to keep. :person_shrugging:

2 Likes

I’m also seeing https://goo.gl/maps and https://goo.gl/photos/ and expect those too will not be affected.

2 Likes

I don’t know. If they work now without a warning then I’d say you’re right.

I’m pretty sure that the script tries to replace those.

3 Likes

The page linked in the OP says:

Note that goo.gl links generated via Google apps (such as Maps sharing) will continue to function.

so presumably, yes, they will continue to work. Especially if no interstitials show up.

Do you have specific ones you can post? Possibly https://goo.gl/maps/ID can be replaced with https://maps.app.goo.gl/ID, though it doesn’t work in the other direction.

Regardless, there’s probably no harm in replacing them?

2 Likes

Hard to say. Probably?

I’m trying not to spend another 5 hours on this 2 hour job, but here are a couple

https://goo.gl/maps/bFFQr8eL4F62

https://goo.gl/maps/BPCy1us5GkJQ2zMX8 becomes

https://www.google.com/maps/place/SUZUKI%E9%91%AB%E6%BD%A4%E8%BB%8A%E6%A5%AD-%E9%B4%BB%E5%AF%B6%E5%8F%B0%E5%8C%97%E6%97%97%E8%89%A6%E5%BA%97/@25.0488943,121.5803302,16.17z/data=!4m5!3m4!1s0x3442ab9666e0cf09:0x7be03675872f9c63!8m2!3d25.051748!4d121.5809526?shorturl=1

So it’s probably safe to modify

    if match.include?('maps.app.goo.gl')

to something like

    if match.include?('maps.app.goo.gl') || match.include?('goo.gl/maps')

And maybe also add the pictures one.

And I also just learned that you also need to rebake posts that onebox the replaced URLs.

I think a proper rake task with some specs is probably in order, but I’ve already got at least 3X the hours in this job that I billed for it.

I was only wondering if these were equivalent:

https://goo.gl/maps/bFFQr8eL4F62
https://maps.app.goo.gl/bFFQr8eL4F62

but this is not the case.

All signs point to the former continuing to work anyways :+1:

2 Likes