diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab95271..9d3022f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,9 @@ jobs: with: java-version: 11 + - name: Install sbt + uses: sbt/setup-sbt@v1 + - name: Run tests run: sbt coverage +test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9257f99..83f3a0e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,6 +12,9 @@ jobs: - uses: actions/checkout@v2 - uses: coursier/cache-action@v6 + - name: Install sbt + uses: sbt/setup-sbt@v1 + - name: Make site run: sbt makeSite diff --git a/src/main/scala/com/snowplowanalytics/refererparser/Medium.scala b/src/main/scala/com/snowplowanalytics/refererparser/Medium.scala index 2f69b57..e4a36e6 100644 --- a/src/main/scala/com/snowplowanalytics/refererparser/Medium.scala +++ b/src/main/scala/com/snowplowanalytics/refererparser/Medium.scala @@ -29,6 +29,7 @@ object Medium { case SocialMedium.value => Some(SocialMedium) case EmailMedium.value => Some(EmailMedium) case PaidMedium.value => Some(PaidMedium) + case ChatbotMedium.value => Some(ChatbotMedium) case _ => None } @@ -38,6 +39,7 @@ object Medium { val Social = SocialMedium val Email = EmailMedium val Paid = PaidMedium + val Chatbot = ChatbotMedium } case object UnknownMedium extends Medium("unknown") @@ -46,3 +48,4 @@ case object InternalMedium extends Medium("internal") case object SocialMedium extends Medium("social") case object EmailMedium extends Medium("email") case object PaidMedium extends Medium("paid") +case object ChatbotMedium extends Medium("chatbot") diff --git a/src/main/scala/com/snowplowanalytics/refererparser/Parser.scala b/src/main/scala/com/snowplowanalytics/refererparser/Parser.scala index 8230fa4..6f38fdf 100644 --- a/src/main/scala/com/snowplowanalytics/refererparser/Parser.scala +++ b/src/main/scala/com/snowplowanalytics/refererparser/Parser.scala @@ -120,6 +120,7 @@ class Parser private[refererparser] (referers: Map[String, RefererLookup]) { case SocialMedium => SocialReferer(SocialMedium, lookup.source) case EmailMedium => EmailReferer(EmailMedium, lookup.source) case PaidMedium => PaidReferer(PaidMedium, lookup.source) + case ChatbotMedium => ChatbotReferer(ChatbotMedium, lookup.source) } } .getOrElse(UnknownReferer(UnknownMedium)) diff --git a/src/main/scala/com/snowplowanalytics/refererparser/Referer.scala b/src/main/scala/com/snowplowanalytics/refererparser/Referer.scala index 90fe480..1852897 100644 --- a/src/main/scala/com/snowplowanalytics/refererparser/Referer.scala +++ b/src/main/scala/com/snowplowanalytics/refererparser/Referer.scala @@ -29,3 +29,4 @@ final case class InternalReferer(medium: Medium) extends Referer final case class SocialReferer(medium: Medium, source: String) extends Referer final case class EmailReferer(medium: Medium, source: String) extends Referer final case class PaidReferer(medium: Medium, source: String) extends Referer +final case class ChatbotReferer(medium: Medium, source: String) extends Referer diff --git a/src/test/resources/referer-tests.json b/src/test/resources/referer-tests.json index 4233d96..eab3d56 100644 --- a/src/test/resources/referer-tests.json +++ b/src/test/resources/referer-tests.json @@ -246,5 +246,37 @@ "source": null, "term": null, "known": false - } + }, + { + "spec": "ChatGPT", + "uri": "https://www.chatgpt.com", + "medium": "chatbot", + "source": "ChatGPT", + "term": null, + "known": true + }, + { + "spec": "Google Gemini", + "uri": "https://gemini.google.com", + "medium": "chatbot", + "source": "Google Gemini", + "term": null, + "known": true + }, + { + "spec": "Microsoft Copilot", + "uri": "https://www.copilot.microsoft.com/account?u=1&id=1", + "medium": "chatbot", + "source": "Microsoft Copilot", + "term": null, + "known": true + }, + { + "spec": "META.ai", + "uri": "https://meta.ai", + "medium": "chatbot", + "source": "META.ai", + "term": null, + "known": true + } ] diff --git a/src/test/resources/referers.json b/src/test/resources/referers.json index 680f910..b17f4e6 100644 --- a/src/test/resources/referers.json +++ b/src/test/resources/referers.json @@ -1100,5 +1100,28 @@ "odnoklassniki.ru" ] } + }, + "chatbot": { + "ChatGPT": { + "domains": [ + "chatgpt.com", + "chat.openai.com" + ] + }, + "Google Gemini": { + "domains": [ + "gemini.google.com" + ] + }, + "Microsoft Copilot": { + "domains": [ + "copilot.microsoft.com" + ] + }, + "META.ai": { + "domains": [ + "meta.ai" + ] + } } } diff --git a/src/test/scala/com/snowplowanalytics/refererparser/JsonParseTest.scala b/src/test/scala/com/snowplowanalytics/refererparser/JsonParseTest.scala index d6051c1..b7551c4 100644 --- a/src/test/scala/com/snowplowanalytics/refererparser/JsonParseTest.scala +++ b/src/test/scala/com/snowplowanalytics/refererparser/JsonParseTest.scala @@ -72,6 +72,7 @@ class JsonParseTest extends Specification { case Some(SocialMedium) => Some(SocialReferer(SocialMedium, test.source.get)) case Some(EmailMedium) => Some(EmailReferer(EmailMedium, test.source.get)) case Some(PaidMedium) => Some(PaidReferer(PaidMedium, test.source.get)) + case Some(ChatbotMedium) => Some(ChatbotReferer(ChatbotMedium, test.source.get)) case _ => throw new Exception(s"Bad medium: ${test.medium}") } val ioActual = ioParser.parse(new URI(test.uri), Some(pageHost), internalDomains) diff --git a/src/test/scala/com/snowplowanalytics/refererparser/ParseTest.scala b/src/test/scala/com/snowplowanalytics/refererparser/ParseTest.scala index 610c89a..b09d1ed 100644 --- a/src/test/scala/com/snowplowanalytics/refererparser/ParseTest.scala +++ b/src/test/scala/com/snowplowanalytics/refererparser/ParseTest.scala @@ -396,6 +396,42 @@ class ParseTest extends Specification with DataTables { Some("keyword 1%") ) ) + test( + RefererSpec( + "ChatGPT", + "https://www.chatgpt.com", + Medium.Chatbot, + Some("ChatGPT"), + None + ) + ) + test( + RefererSpec( + "Google Gemini", + "https://gemini.google.com", + Medium.Chatbot, + Some("Google Gemini"), + None + ) + ) + test( + RefererSpec( + "Microsoft Copilot", + "https://www.copilot.microsoft.com/account?u=1&id=1", + Medium.Chatbot, + Some("Microsoft Copilot"), + None + ) + ) + test( + RefererSpec( + "META.ai", + "https://meta.ai", + Medium.Chatbot, + Some("META.ai"), + None + ) + ) } def genExpected(medium: Medium, source: Option[String], term: Option[String]) = @@ -406,5 +442,6 @@ class ParseTest extends Specification with DataTables { case SocialMedium => SocialReferer(SocialMedium, source.get) case EmailMedium => EmailReferer(EmailMedium, source.get) case PaidMedium => PaidReferer(PaidMedium, source.get) + case ChatbotMedium => ChatbotReferer(ChatbotMedium, source.get) } }