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

Parse url query param from Google Alerts feeds #717

Merged
merged 1 commit into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion capy/src/main/java/com/jocmp/capy/Account.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package com.jocmp.capy
import com.jocmp.capy.accounts.AddFeedResult
import com.jocmp.capy.accounts.AutoDelete
import com.jocmp.capy.accounts.FaviconFetcher
import com.jocmp.capy.accounts.LocalAccountDelegate
import com.jocmp.capy.accounts.LocalOkHttpClient
import com.jocmp.capy.accounts.Source
import com.jocmp.capy.accounts.asOPML
import com.jocmp.capy.accounts.feedbin.FeedbinAccountDelegate
import com.jocmp.capy.accounts.feedbin.FeedbinOkHttpClient
import com.jocmp.capy.accounts.local.LocalAccountDelegate
import com.jocmp.capy.accounts.reader.buildReaderDelegate
import com.jocmp.capy.articles.ArticleContent
import com.jocmp.capy.articles.UnreadSortOrder
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package com.jocmp.capy.accounts

import com.jocmp.capy.UserAgentInterceptor
import okhttp3.Cache
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.brotli.BrotliInterceptor
import java.io.File
import java.net.URI

internal object LocalOkHttpClient {
Expand Down
27 changes: 27 additions & 0 deletions capy/src/main/java/com/jocmp/capy/accounts/local/ArticleURL.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.jocmp.capy.accounts.local

import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import java.net.MalformedURLException
import java.net.URL

internal object ArticleURL {
internal fun parse(url: URL): URL {
return googleAlertURL(url) ?: url
}

private fun googleAlertURL(url: URL): URL? {
if (url.host != GOOGLE_ALERTS_DOMAIN) {
return null
}

val articleURLParam = url.toHttpUrlOrNull()?.queryParameter("url") ?: return null

return try {
URL(articleURLParam)
} catch (e: MalformedURLException) {
null
}
}

private const val GOOGLE_ALERTS_DOMAIN = "www.google.com"
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.jocmp.capy.accounts
package com.jocmp.capy.accounts.local

import com.jocmp.capy.AccountDelegate
import com.jocmp.capy.ArticleFilter
import com.jocmp.capy.Feed
import com.jocmp.capy.accounts.AddFeedResult
import com.jocmp.capy.accounts.FaviconFetcher
import com.jocmp.capy.accounts.FeedOption
import com.jocmp.capy.common.TimeHelpers.nowUTC
import com.jocmp.capy.common.TimeHelpers.published
import com.jocmp.capy.common.transactionWithErrorHandling
Expand All @@ -23,7 +26,7 @@ import java.net.UnknownHostException
import java.time.ZonedDateTime
import com.jocmp.feedfinder.parser.Feed as ParserFeed

class LocalAccountDelegate(
internal class LocalAccountDelegate(
private val database: Database,
private val httpClient: OkHttpClient,
private val faviconFetcher: FaviconFetcher,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.jocmp.capy.accounts
package com.jocmp.capy.accounts.local

import com.jocmp.capy.common.escapingHTMLCharacters
import com.jocmp.rssparser.model.RssItem
Expand All @@ -8,7 +8,7 @@ import java.net.URI
import java.net.URL

internal class ParsedItem(private val item: RssItem, private val siteURL: String?) {
val url: String? = cleanedURL(item.link)?.toString()
val url: String? = articleURL()

val id: String? = url ?: item.guid

Expand Down Expand Up @@ -40,6 +40,12 @@ internal class ParsedItem(private val item: RssItem, private val siteURL: String
val imageURL: String?
get() = cleanedURL(item.image)?.toString()

private fun articleURL(): String? {
val link = cleanedURL(item.link) ?: return null

return ArticleURL.parse(link).toString()
}

private fun cleanedURL(inputURL: String?): URL? {
val url = inputURL.orEmpty()

Expand Down
2 changes: 1 addition & 1 deletion capy/src/test/java/com/jocmp/capy/OPMLFileTest.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.jocmp.capy

import com.jocmp.capy.accounts.FakeFaviconFetcher
import com.jocmp.capy.accounts.LocalAccountDelegate
import com.jocmp.capy.accounts.local.LocalAccountDelegate
import com.jocmp.capy.db.Database
import com.jocmp.capy.fixtures.AccountFixture
import com.jocmp.capy.fixtures.FeedFixture
Expand Down
26 changes: 26 additions & 0 deletions capy/src/test/java/com/jocmp/capy/accounts/local/ArticleURLTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.jocmp.capy.accounts.local

import java.net.URL
import kotlin.test.Test
import kotlin.test.assertEquals

class ArticleURLTest {
@Test
fun `entry URL is the same as article URL`() {
val entryURL = URL("https://www.theverge.com/2025/1/12/24340818/robot-vacuum-innovations-roborock-dreame-ecovacs-ces2025")

val url = ArticleURL.parse(url = entryURL)

assertEquals(expected = entryURL.toString(), actual = url.toString())
}

@Test
fun `with a Google Alert entry URL it returns the url param`() {
val entryURL = URL("https://www.google.com/url?rct=j&sa=t&url=https://www.androidheadlines.com/2025/01/meta-sued-for-allegedly-training-ai-with-content-from-pirated-books.html&ct=ga&cd=CAIyGjQ2MjY4NTIwYjAzMGNkMzc6Y29tOmVuOlVT&usg=AOvVaw2Ez54Yz16bwLLLX_YLfwA2")
val articleURL = URL("https://www.androidheadlines.com/2025/01/meta-sued-for-allegedly-training-ai-with-content-from-pirated-books.html")

val url = ArticleURL.parse(url = entryURL)

assertEquals(expected = articleURL.toString(), actual = url.toString())
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.jocmp.capy.accounts
package com.jocmp.capy.accounts.local

import com.jocmp.capy.AccountDelegate
import com.jocmp.capy.ArticleFilter
import com.jocmp.capy.InMemoryDatabaseProvider
import com.jocmp.capy.accounts.AddFeedResult
import com.jocmp.capy.accounts.FakeFaviconFetcher
import com.jocmp.capy.db.Database
import com.jocmp.capy.fixtures.FeedFixture
import com.jocmp.capy.logging.CapyLog
Expand Down Expand Up @@ -118,7 +120,10 @@ class LocalAccountDelegateTest {

FeedFixture(database).create(feedID = channel.link!!)

delegate.refresh(ArticleFilter.default(), cutoffDate = ZonedDateTime.of(2024, 5, 1, 8, 0, 0, 0, ZoneOffset.UTC))
delegate.refresh(
ArticleFilter.default(),
cutoffDate = ZonedDateTime.of(2024, 5, 1, 8, 0, 0, 0, ZoneOffset.UTC)
)

val articlesCount = database
.articlesQueries
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.jocmp.capy.accounts
package com.jocmp.capy.accounts.local

import com.jocmp.rssparser.model.RssItem
import kotlin.test.Test
Expand Down Expand Up @@ -31,7 +31,10 @@ class ParsedItemTest {
val item = RssItem.Builder().title(title).build()
val parsedItem = ParsedItem(item, siteURL = "")

assertEquals(expected = "The `<details>` and `<summary>` elements are getting an upgrade", actual = parsedItem.title)
assertEquals(
expected = "The `<details>` and `<summary>` elements are getting an upgrade",
actual = parsedItem.title
)
}

@Test
Expand Down Expand Up @@ -116,4 +119,15 @@ class ParsedItemTest {

assertEquals(expected = "https://example.com/article", actual = parsedItem.url)
}

@Test
fun url_withGoogleAlertsFeed() {
val articleURL = "https://www.androidcentral.com/apps-software/google-squashes-a-few-pixel-bugs-in-android-15-qpr2-beta-2-1"
val link = "https://www.google.com/url?rct=j&sa=t&url=$articleURL&ct=ga&cd=CAIyGmNmNDdiZGVhOWNiNDUxZTA6Y29tOmVuOlVT&usg=AOvVaw0NIyLHLSRUIwSMg9anVWrG"

val item = RssItem.Builder().link(link).build()
val parsedItem = ParsedItem(item, siteURL = "https://www.google.com/alerts/feeds/12345/12345")

assertEquals(expected = articleURL, actual = parsedItem.url)
}
}
2 changes: 1 addition & 1 deletion capy/src/test/java/com/jocmp/capy/opml/OPMLImporterTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.jocmp.capy.Account
import com.jocmp.capy.InMemoryDatabaseProvider
import com.jocmp.capy.MockFeedFinder
import com.jocmp.capy.accounts.FakeFaviconFetcher
import com.jocmp.capy.accounts.LocalAccountDelegate
import com.jocmp.capy.accounts.local.LocalAccountDelegate
import com.jocmp.capy.db.Database
import com.jocmp.capy.fixtures.AccountFixture
import com.jocmp.capy.fixtures.GenericFeed
Expand Down
Loading