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

Release 0.41.0 #32

Merged
merged 8 commits into from
Sep 10, 2024
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
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ android {

defaultConfig {
applicationId = "com.kafka.user"
versionCode = 80
versionName = "0.40.0"
versionCode = 82
versionName = "0.42.0"

val properties = Properties()
properties.load(project.rootProject.file("local.properties").inputStream())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class AnalyticsImpl @Inject constructor(
}

override fun updateUserProperty(userData: UserData) {
debug { "Updating user properties: $userData" }
firebaseAnalytics.setUserId(userData.userId)
firebaseAnalytics.setUserProperty("userId", userData.userId)
firebaseAnalytics.setUserProperty("country", userData.country)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class RemoteConfig @Inject constructor(private val json: Json) {
minimumFetchIntervalInSeconds = REMOTE_CONFIG_FETCH_INTERVAL_SECONDS
}
setConfigSettingsAsync(config)
setDefaultsAsync(R.xml.remote_config_defaults)
}
}

Expand Down
91 changes: 91 additions & 0 deletions core/remote-config/src/main/res/xml/remote_config_defaults.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<defaults>
<entry>
<key>summary_enabled</key>
<value>false</value>
</entry>
<entry>
<key>show_featured_item_labels</key>
<value>true</value>
</entry>
<entry>
<key>use_recommendation_data_enabled</key>
<value>false</value>
</entry>
<entry>
<key>min_supported_version</key>
<value>60</value>
</entry>
<entry>
<key>is_share_enabled</key>
<value>true</value>
</entry>
<entry>
<key>downloads_warning_message</key>
<value>Downloads may be slow or unreliable depending on the server and internet connectivity.</value>
</entry>
<entry>
<key>borrowable_book_message</key>
<value>This item has restricted access. You can borrow it for free by logging into the website.|| ||Please note that the Internet Archive login is different from the Kafka login, so you may need to sign up on the website.</value>
</entry>
<entry>
<key>true_contrast_enabled</key>
<value>true</value>
</entry>
<entry>
<key>downloader_type</key>
<value>sequential</value>
</entry>
<entry>
<key>homepage_items_shuffle_enabled</key>
<value>false</value>
</entry>
<entry>
<key>player_theme</key>
<value>album</value>
</entry>
<entry>
<key>is_placeholder_enabled</key>
<value>false</value>
</entry>
<entry>
<key>google_login_enabled</key>
<value>true</value>
</entry>
<entry>
<key>recommendation_row_index</key>
<value>5</value>
</entry>
<entry>
<key>recommendation_row_enabled</key>
<value>false</value>
</entry>
<entry>
<key>online_reader_enabled</key>
<value>true</value>
</entry>
<entry>
<key>view_recommendation_data_enabled</key>
<value>false</value>
</entry>
<entry>
<key>share_app_index</key>
<value>6</value>
</entry>
<entry>
<key>exact_alarm_enabled</key>
<value>false</value>
</entry>
<entry>
<key>item_detail_dynamic_theme_enabled</key>
<value>true</value>
</entry>
<entry>
<key>recommendation_data_enabled</key>
<value>false</value>
</entry>
<entry>
<key>related_content_row_enabled</key>
<value>false</value>
</entry>
</defaults>
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,14 @@ interface KafkaDatabase {
RecentAudioItem::class,
DownloadRequest::class,
],
version = 7,
version = 8,
exportSchema = true,
autoMigrations = [
AutoMigration(from = 3, to = 4, spec = KafkaRoomDatabase.UserRemovalMigration::class),
AutoMigration(from = 4, to = 5, spec = KafkaRoomDatabase.RecentAudioMigration::class)
AutoMigration(from = 4, to = 5, spec = KafkaRoomDatabase.RecentAudioMigration::class),
AutoMigration(from = 5, to = 8),
AutoMigration(from = 6, to = 8),
AutoMigration(from = 7, to = 8),
],
)
@TypeConverters(AppTypeConverters::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ data class ItemDetail(
val title: String? = null,
val description: String? = null,
val creator: String? = null,
val creators: List<String>? = null,
val collection: String? = null,
val mediaType: String? = null,
val coverImage: String? = null,
Expand All @@ -26,7 +27,7 @@ data class ItemDetail(
val primaryFile: String? = null,
val subject: List<String>? = null,
val rating: Double? = null,
val isAccessRestricted: Boolean = false
val isAccessRestricted: Boolean = false,
) : BaseEntity {
val uiRating: Int
get() = (rating ?: 0.0).toInt()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.aallam.openai.api.http.Timeout
import com.aallam.openai.api.model.ModelId
import com.aallam.openai.client.OpenAI
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import org.kafka.base.SecretsProvider
Expand Down Expand Up @@ -40,6 +41,7 @@ class OpenAiRepository @Inject constructor(secretsProvider: SecretsProvider) {
return openai.chatCompletions(completionRequest)
.onEach { result += it.choices.firstOrNull()?.delta?.content.orEmpty() }
.map { SummaryResponse(result, it.choices.firstOrNull()?.finishReason != null) }
.catch { it.printStackTrace() }
}

private val model = ModelId("gpt-4o")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class ItemDetailMapper @Inject constructor(
title = from.metadata.title?.firstOrNull()?.dismissUpperCase(),
description = from.metadata.description?.joinToString()?.format() ?: "",
creator = from.metadata.creator?.take(5)?.joinToString()?.sanitizeForRoom(),
creators = from.metadata.creator?.map { it.sanitizeForRoom() }?.take(5),
collection = from.metadata.collection?.joinToString(),
mediaType = from.metadata.mediatype,
files = from.files.filter { it.fileId.isNotEmpty() }.map { it.fileId },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.kafka.domain.observers

import com.kafka.data.dao.FileDao
import com.kafka.data.dao.ItemDetailDao
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import org.kafka.base.CoroutineDispatchers
import org.kafka.base.domain.SubjectInteractor
import javax.inject.Inject

class ShouldAutoDownload @Inject constructor(
private val dispatchers: CoroutineDispatchers,
private val itemDetailDao: ItemDetailDao,
private val fileDao: FileDao,
) : SubjectInteractor<ShouldAutoDownload.Param, Boolean>() {

override fun createObservable(params: Param): Flow<Boolean> {
return itemDetailDao.observeItemDetail(params.itemId)
.map { itemDetail ->
val file = fileDao.getOrNull(itemDetail?.primaryFile.orEmpty())
(file?.size ?: 0) < 10000000L
}.flowOn(dispatchers.io)
}

data class Param(val itemId: String)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.kafka.domain.observers

import com.kafka.data.dao.FileDao
import com.kafka.data.dao.ItemDetailDao
import com.kafka.remote.config.RemoteConfig
import com.kafka.remote.config.isOnlineReaderEnabled
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOn
import org.kafka.base.CoroutineDispatchers
import org.kafka.base.domain.SubjectInteractor
import org.kafka.domain.observers.library.ObserveDownloadByItemId
import javax.inject.Inject

class ShouldUseOnlineReader @Inject constructor(
private val dispatchers: CoroutineDispatchers,
private val observeDownloadByItemId: ObserveDownloadByItemId,
private val itemDetailDao: ItemDetailDao,
private val fileDao: FileDao,
private val remoteConfig: RemoteConfig,
) : SubjectInteractor<ShouldUseOnlineReader.Param, Boolean>() {

override fun createObservable(params: Param): Flow<Boolean> {
return combine(
itemDetailDao.observeItemDetail(params.itemId),
observeDownloadByItemId.createObservable(ObserveDownloadByItemId.Params(params.itemId))
) { itemDetail, download ->
val file = fileDao.getOrNull(itemDetail?.primaryFile.orEmpty())
if (itemDetail == null || file == null) {
return@combine false
}

val isOnlineReaderEnabled = download == null && remoteConfig.isOnlineReaderEnabled()

isOnlineReaderEnabled || itemDetail.isAccessRestricted
}.flowOn(dispatchers.io)
}

data class Param(val itemId: String)
}
18 changes: 9 additions & 9 deletions functions/recommendation/collaborative.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ async function calculateCollaborativeRecommendations() {
async function getActiveUsers() {
const query = `
SELECT
user_pseudo_id AS user_id
user_id
FROM (
SELECT
user_pseudo_id,
user_id,
COUNT(*) AS open_item_detail_count
FROM
\`kafka-books.analytics_195726967.events_*\`
Expand All @@ -87,22 +87,22 @@ async function getActiveUsers() {
AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
AND event_name = 'open_item_detail'
GROUP BY
user_pseudo_id
user_id
HAVING
open_item_detail_count > 5
) AS active_users
WHERE
user_pseudo_id IN (
user_id IN (
SELECT DISTINCT
user_pseudo_id
user_id
FROM
\`kafka-books.analytics_195726967.events_*\`
WHERE
_TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL ${ACTIVE_USER_THRESHOLD_DAYS} DAY))
AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
AND event_name IN (${EVENTS_OF_INTEREST.map(event => `'${event}'`).join(',')})
)
LIMIT 50
LIMIT 500
`;

// Log the query before execution
Expand All @@ -115,7 +115,7 @@ async function getActiveUsers() {
async function getUserInteractions(activeUsers) {
const query = `
SELECT
user_pseudo_id AS user_id,
user_id,
event_name,
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'item_id') AS item_id,
COUNT(*) AS interaction_count
Expand All @@ -124,8 +124,8 @@ async function getActiveUsers() {
WHERE
PARSE_DATE('%Y%m%d', _TABLE_SUFFIX) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL ${ACTIVE_USER_THRESHOLD_DAYS} DAY) AND CURRENT_DATE()
AND event_name IN (${EVENTS_OF_INTEREST.map(event => `'${event}'`).join(',')})
AND user_pseudo_id IN (${activeUsers.map(user => `'${user}'`).join(',')})
AND user_pseudo_id IS NOT NULL
AND user_id IN (${activeUsers.map(user => `'${user}'`).join(',')})
AND user_id IS NOT NULL
GROUP BY
user_id, event_name, item_id
HAVING
Expand Down
Loading