Skip to content

Commit

Permalink
Release v1.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
wb14123 committed Oct 15, 2024
1 parent 5802a7e commit 6e16da1
Show file tree
Hide file tree
Showing 29 changed files with 442 additions and 52 deletions.
35 changes: 35 additions & 0 deletions js/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -974,3 +974,38 @@ popover-content a:hover {
padding: 0 0 0 0;
font-size: 0; /* needed for Chrome */
}

/* nsfw */
.article-desc-nsfw {
font-size: 18px;
color: var(--pico-code-color);
display: none;
}

.nsfw-blur .nsfw .article-media img {
filter: blur(20px);
}

.nsfw-blur .nsfw .article-desc {
display: none;
}

.nsfw-blur .nsfw .article-desc-nsfw {
display: block;
}

.nsfw-hide .nsfw .article-media img {
display: none;
}

.nsfw-hide .nsfw .article-desc {
display: none;
}

.nsfw-hide .nsfw .article-desc-nsfw {
display: block;
}

.nsfw-show .nsfw .article-desc-nsfw {
display: none;
}
8 changes: 4 additions & 4 deletions js/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"htmx.org": "^1.9.12",
"imgs-html": "^0.0.4",
"lite-youtube-embed": "^0.3.3",
"somment": "^0.0.1",
"somment": "^0.0.2",
"toastify-js": "^1.12.0",
"viewerjs": "^1.11.6"
},
Expand Down
3 changes: 2 additions & 1 deletion js/src/error-handler.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@

function showErrorMessage(errMsg, details) {
const maxLength = 100;
Toastify({
text: errMsg,
text: errMsg.substring(0, maxLength),
className: 'error-toast',
duration: 30000,
newWindow: false,
Expand Down
7 changes: 7 additions & 0 deletions js/src/set-theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,11 @@ function initTheme() {
setTheme(getCurrentTheme());
}

async function loadNSFWClass() {
const res = await fetch("/hx/settings/nsfw", {method: 'GET'});
const setting = await res.text();
return "nsfw-" + setting.toLowerCase();
}
window.loadNSFWClass = loadNSFWClass;

initTheme();
30 changes: 30 additions & 0 deletions src/main/protobuf/grpc-api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,21 @@ message SourceUpdater {
optional IconUrlOption iconUrl = 15;
}

// Define NSFWSetting

enum NSFWSetting {
HIDE = 0;
BLUR = 1;
SHOW = 2;
}

// Define SearchEngine

message SearchEngine {
optional string name = 1;
string urlPrefix = 2;
}

// Define User

message User {
Expand All @@ -294,6 +309,8 @@ message User {
optional string activeCode = 14;
int64 subscribeEndAt = 15;
bool subscribed = 16;
NSFWSetting nsfwSetting = 17;
SearchEngine searchEngine = 18;
}

// Define UserInfo
Expand All @@ -309,6 +326,8 @@ message UserInfo {
optional string currentFolderID = 8;
optional string currentSourceID = 9;
bool subscribed = 10;
NSFWSetting nsfwSetting = 11;
SearchEngine searchEngine = 12;
}

// Define UserUpdater
Expand Down Expand Up @@ -347,6 +366,8 @@ message UserUpdater {
optional int64 subscribeEndAt = 11;
optional bool subscribed = 12;
optional string username = 13;
optional NSFWSetting nsfwSetting = 14;
optional SearchEngine searchEngine = 15;
}

// Define UserSession
Expand Down Expand Up @@ -1250,6 +1271,12 @@ message SetCurrentSourceRequest {
string currentSourceID = 2;
}

message UpdateUserSettingsRequest {
string token = 1;
optional NSFWSetting nsfwSetting = 2;
optional SearchEngine searchEngine = 3;
}

message RemoveCurrentFolderAndSourceRequest {
string token = 1;
}
Expand Down Expand Up @@ -1311,6 +1338,8 @@ message SetCurrentFolderResponse {}

message SetCurrentSourceResponse {}

message UpdateUserSettingsResponse {}

message RemoveCurrentFolderAndSourceResponse {}

message GetPaymentCustomersResponse {
Expand All @@ -1337,6 +1366,7 @@ service UserAPI {
rpc GetRedditSessions (GetRedditSessionsRequest) returns (stream GetRedditSessionsResponse);
rpc SetCurrentFolder (SetCurrentFolderRequest) returns (SetCurrentFolderResponse);
rpc SetCurrentSource (SetCurrentSourceRequest) returns (SetCurrentSourceResponse);
rpc UpdateUserSettings (UpdateUserSettingsRequest) returns (UpdateUserSettingsResponse);
rpc RemoveCurrentFolderAndSource (RemoveCurrentFolderAndSourceRequest) returns (RemoveCurrentFolderAndSourceResponse);
rpc GetPaymentCustomers (GetPaymentCustomersRequest) returns (stream GetPaymentCustomersResponse);
rpc SendDeleteUserCode (SendDeleteUserCodeRequest) returns (SendDeleteUserCodeResponse);
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ redis {
}

api {
version = "1.4.0"
version = "1.5.0"
}

grpc {
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/me/binwang/rss/cmd/GRPCAndHttpServer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ object GRPCAndHttpServer extends IOApp {
new PaymentView(services.userService, services.stripePaymentService).routes <+>
new ImportFeedView(services.sourceService, services.folderService).routes <+>
new RecommendationView(services.moreLikeThisService, services.articleService, services.sourceService,
services.folderService).routes
services.folderService, services.userService).routes
)))
HttpServer(httpRoute, config.getString("frontend.ip"), config.getInt("frontend.port"), logBody = false)
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/me/binwang/rss/cmd/HttpServer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import org.http4s.HttpRoutes
import org.http4s.ember.server.EmberServerBuilder
import org.http4s.implicits._
import org.http4s.server.Server
import org.http4s.server.middleware.{ErrorAction, Logger}
import org.http4s.server.middleware.{ErrorAction, GZip, Logger}
import org.typelevel.log4cats.LoggerFactory
import org.typelevel.log4cats.slf4j.Slf4jFactory

Expand All @@ -25,7 +25,7 @@ object HttpServer {
)(routes)

val httpService = ErrorAction.httpRoutes[IO](
loggingService,
GZip(loggingService),
(req, thr) => http4sLogger.error(thr)(s"Error when handling request: ${req.uri}")
).orNotFound

Expand Down
28 changes: 26 additions & 2 deletions src/main/scala/me/binwang/rss/dao/sql/BaseSqlDao.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import me.binwang.rss.model.EmbeddingUpdateStatus.EmbeddingUpdateStatus
import me.binwang.rss.model.FetchStatus.FetchStatus
import me.binwang.rss.model.ID.ID
import me.binwang.rss.model.MoreLikeThisType.MoreLikeThisType
import me.binwang.rss.model.NSFWSetting.NSFWSetting
import me.binwang.rss.model._
import org.postgresql.util.PGobject

Expand Down Expand Up @@ -88,15 +89,21 @@ trait BaseSqlDao {
protected implicit val encodeArticleListLayout: MappedEncoding[ArticleListLayout, String] =
MappedEncoding[ArticleListLayout, String](_.toString)

protected implicit val jsonbEncoder: Encoder[MediaGroups] = encoder(java.sql.Types.OTHER, (index, mediaGroups, row) => {
protected implicit val decodeNsfwSetting: MappedEncoding[String, NSFWSetting] =
MappedEncoding[String, NSFWSetting](NSFWSetting.withName)

protected implicit val encodeNsfwSetting: MappedEncoding[NSFWSetting, String] =
MappedEncoding[NSFWSetting, String](_.toString)

protected implicit val mediaGroupsEncoder: Encoder[MediaGroups] = encoder(java.sql.Types.OTHER, (index, mediaGroups, row) => {
val value = io.circe.syntax.EncoderOps(mediaGroups).asJson.toString()
val pgObj = new PGobject()
pgObj.setType("jsonb")
pgObj.setValue(value)
row.setObject(index, pgObj)
})

protected implicit val jsonbDecoder: Decoder[MediaGroups] = decoder { (index, row, _) =>
protected implicit val mediaGroupsDecoder: Decoder[MediaGroups] = decoder { (index, row, _) =>
val defaultMediaGroups = MediaGroups(groups = Seq())
val pgObj = row.getObject(index).asInstanceOf[PGobject]
if (pgObj == null) {
Expand All @@ -106,6 +113,23 @@ trait BaseSqlDao {
}
}

protected implicit val searchEngineEncoder: Encoder[SearchEngine] = encoder(java.sql.Types.OTHER, (index, searchEngine, row) => {
val value = io.circe.syntax.EncoderOps(searchEngine).asJson.toString()
val pgObj = new PGobject()
pgObj.setType("jsonb")
pgObj.setValue(value)
row.setObject(index, pgObj)
})

protected implicit val searchEngineDecoder: Decoder[SearchEngine] = decoder { (index, row, _) =>
val pgObj = row.getObject(index).asInstanceOf[PGobject]
if (pgObj == null) {
SearchEngine.DEFAULT
} else {
parser.parse(pgObj.getValue).flatMap(_.as[SearchEngine]).getOrElse(SearchEngine.DEFAULT)
}
}


def createTable(): IO[Unit]

Expand Down
4 changes: 3 additions & 1 deletion src/main/scala/me/binwang/rss/dao/sql/ConnectionPool.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import com.zaxxer.hikari.HikariConfig
import doobie.hikari.HikariTransactor

object ConnectionPool {
def apply(): Resource[IO, ConnectionPool] = {

def apply(isolationLevel: String = IsolationLevel.SERIALIZABLE): Resource[IO, ConnectionPool] = {

val config = ConfigFactory.load()

Expand All @@ -17,6 +18,7 @@ object ConnectionPool {
hikariConfig.setPassword(config.getString("db.password"))
hikariConfig.setMaximumPoolSize(config.getInt("db.maxPoolSize"))
hikariConfig.setMinimumIdle(config.getInt("db.minIdle"))
hikariConfig.setTransactionIsolation(isolationLevel)

HikariTransactor.fromHikariConfig[IO](hikariConfig).map(ConnectionPool(_))
}
Expand Down
6 changes: 6 additions & 0 deletions src/main/scala/me/binwang/rss/dao/sql/IsolationLevel.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package me.binwang.rss.dao.sql

object IsolationLevel {
val SERIALIZABLE = "TRANSACTION_SERIALIZABLE"
val READ_COMMITTED = "TRANSACTION_READ_COMMITTED"
}
8 changes: 6 additions & 2 deletions src/main/scala/me/binwang/rss/dao/sql/UserSqlDao.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ class UserSqlDao(implicit val connectionPool: ConnectionPool) extends UserDao wi
currentSourceID char(${ID.maxLength}) default null,
activeCode char($UUID_LENGTH) unique default null,
subscribeEndAt timestamp not null,
subscribed boolean not null default false
subscribed boolean not null default false,
nsfwSetting varchar not null default 'BLUR',
searchEngine jsonb not null
)
""")
.update
Expand Down Expand Up @@ -89,7 +91,9 @@ class UserSqlDao(implicit val connectionPool: ConnectionPool) extends UserDao wi
setOpt(_.activeCode, updater.activeCode),
setOpt(_.subscribeEndAt, updater.subscribeEndAt),
setOpt(_.subscribed, updater.subscribed),
setOpt(_.username, updater.username)
setOpt(_.username, updater.username),
setOpt(_.nsfwSetting, updater.nsfwSetting),
setOpt(_.searchEngine, updater.searchEngine),
)
run(q).transact(xa).map(_ > 0)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import me.binwang.rss.model.ArticleOrder.ArticleOrder
import me.binwang.rss.model.FetchStatus.FetchStatus
import me.binwang.rss.model.ID.ID
import me.binwang.rss.model.MoreLikeThisType.MoreLikeThisType
import me.binwang.rss.model.NSFWSetting.NSFWSetting
import me.binwang.rss.model._
import me.binwang.rss.service._
import me.binwang.rss.sourcefinder.SourceResult
Expand Down Expand Up @@ -60,6 +61,8 @@ object GenerateGRPC extends GRPCGenerator {
typeOf[FetchStatus],
typeOf[Source],
typeOf[SourceUpdater],
typeOf[NSFWSetting],
typeOf[SearchEngine],
typeOf[User],
typeOf[UserInfo],
typeOf[UserUpdater],
Expand Down
31 changes: 31 additions & 0 deletions src/main/scala/me/binwang/rss/model/User.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,29 @@ package me.binwang.rss.model
import java.time.ZonedDateTime
import java.util.UUID

import me.binwang.rss.model.NSFWSetting.NSFWSetting

object NSFWSetting extends Enumeration {
type NSFWSetting = Value
val
HIDE,
BLUR,
SHOW
= Value
}

case class SearchEngine(name: Option[String], urlPrefix: String)

object SearchEngine {
val DUCKDUCKGO = SearchEngine(Some("DuckDuckGo"), "https://duckduckgo.com/?q=")
val GOOGLE = SearchEngine(Some("Google"), "https://www.google.com/search?q=")
val BING = SearchEngine(Some("Bing"), "https://www.bing.com/search?q=")
val KAGI = SearchEngine(Some("Kagi"), "https://kagi.com/search?q=")

val ALL = Seq(DUCKDUCKGO, GOOGLE, BING, KAGI)
val DEFAULT = DUCKDUCKGO
}

case class User (
id: String,
username: String,
Expand All @@ -20,6 +43,8 @@ case class User (
activeCode: Option[String] = Some(UUID.randomUUID().toString),
subscribeEndAt: ZonedDateTime,
subscribed: Boolean = false,
nsfwSetting: NSFWSetting = NSFWSetting.BLUR,
searchEngine: SearchEngine = SearchEngine.DEFAULT,
) {

def toInfo: UserInfo = {
Expand All @@ -34,6 +59,8 @@ case class User (
isAdmin = isAdmin,
subscribeEndAt = subscribeEndAt,
subscribed = subscribed,
nsfwSetting = nsfwSetting,
searchEngine = searchEngine,
)
}

Expand All @@ -50,6 +77,8 @@ case class UserInfo (
currentFolderID: Option[String] = None,
currentSourceID: Option[String] = None,
subscribed: Boolean = false,
nsfwSetting: NSFWSetting = NSFWSetting.BLUR,
searchEngine: SearchEngine = SearchEngine.DUCKDUCKGO,
)

case class UserUpdater (
Expand All @@ -66,4 +95,6 @@ case class UserUpdater (
subscribeEndAt: Option[ZonedDateTime] = None,
subscribed: Option[Boolean] = None,
username: Option[String] = None,
nsfwSetting: Option[NSFWSetting] = None,
searchEngine: Option[SearchEngine] = None,
)
Loading

0 comments on commit 6e16da1

Please sign in to comment.