""".trimIndent())
createStmt.addBatch("""
- CREATE TABLE feedcollections (
- feedcollection_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
+ CREATE TABLE feeds (
+ feed_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
group_id INT NOT NULL REFERENCES groups(group_id) ON DELETE CASCADE,
pos INT default 0,
- internal_browser INT default 0,
name VARCHAR,
- update_interval INT,
- max_item_age INT DEFAULT 0,
- item_state_mode INT DEFAULT 0,
- add_url_param VARCHAR
- )
- """.trimIndent())
-
- createStmt.addBatch("""
- CREATE TABLE feeds(
- feed_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
- feedcollection_id INT NOT NULL REFERENCES feedcollections(feedcollection_id) ON DELETE CASCADE,
url VARCHAR NOT NULL,
auth_user VARCHAR,
auth_password VARCHAR,
+ internal_browser INT default 0,
+ update_interval INT,
+ max_item_age INT DEFAULT 0,
+ item_state_mode INT DEFAULT 0,
+ add_url_param VARCHAR,
certpath VARCHAR,
last_update TIMESTAMP,
disabled BOOLEAN DEFAULT FALSE
select
g.group_id,
g.name as group_name,
- f.feedcollection_id,
+ f.feed_id,
f.name as feed_name,
+ f.url as feed_url,
+ f.auth_user,
+ f.auth_password,
f.update_interval,
f.max_item_age,
f.item_state_mode,
f.add_url_param,
c.unread_count
from groups g
- left join feedcollections f on g.group_id = f.group_id
- left join (select feedcollection_id, count(*) as unread_count from items I inner join feeds F on I.feed_id = F.feed_id
- where I.is_read = false group by feedcollection_id) C on f.feedcollection_id = C.feedcollection_id
+ left join feeds f on g.group_id = f.group_id
+ left join (select f.feed_id, count(*) as unread_count from items I inner join feeds F on I.feed_id = F.feed_id
+ where I.is_read = false group by f.feed_id) C on f.feed_id = C.feed_id
order by g.pos, f.pos
""".trimIndent())
while(rs.next()) {
val groupId = rs.getInt("group_id")
val groupName = rs.getString("group_name")
- val feedId = rs.getInt("feedcollection_id")
+ val feedId = rs.getInt("feed_id")
val feedName = rs.getString("feed_name")
+ val auth_user = rs.getString("auth_user")
+ val auth_password = rs.getString("auth_password")
+ val feedUrl = rs.getString("feed_url")
val updateInterval = rs.getLong("update_interval")
val maxItemAge = rs.getInt("max_item_age")
val internalBrowser = rs.getBoolean("internal_browser")
}
if(feedId != null && feedName != null) {
- val feed = FeedCollection(feedId, feedName)
+ val feed = Feed(feedId, feedName, feedUrl)
+ feed.user = auth_user
+ feed.password = auth_password
feed.updateInterval = updateInterval
feed.maxItemAge = maxItemAge
feed.itemStateMode = itemStateMode
return groups
}
- public fun swapFeedCollectionPos(feed1: FeedCollection, feed2: FeedCollection) {
+ public fun swapFeedPos(feed1: Feed, feed2: Feed) {
val sql = """
- update feedcollections set
+ update feeds set
pos = case
- when feedcollection_id = ?1 then (SELECT pos from feedcollections where feedcollection_id = ?2)
- when feedcollection_id = ?2 then (SELECT pos from feedcollections where feedcollection_id = ?1)
+ when feed_id = ?1 then (SELECT pos from feeds where feed_id = ?2)
+ when feed_id = ?2 then (SELECT pos from feeds where feed_id = ?1)
else pos
end
- where feedcollection_id in (?1, ?2)
+ where feed_id in (?1, ?2)
""".trimIndent()
dataSource.connection.use { conn ->
return FeedGroup(context, groupId, name)
}
- public fun newFeeds(
+ public fun newFeed(
parent: FeedGroup,
name: String,
- uris: Collection<String>,
+ uri: String,
user: String? = null,
password: String? = null,
cert: String? = null,
internalBrowser: Boolean = false,
updateInterval: Long = 0,
maxItemAge: Int = 0,
- itemStateMode: Int = 0) : FeedCollection
+ itemStateMode: Int = 0) : Feed
{
- var feedcollectionId = -1
- var feedCol: FeedCollection
+ var feedId = -1
+ var feed: Feed
dataSource.connection.use { connection ->
connection.prepareStatement("""
- insert into feedcollections (group_id, pos, name, update_interval, max_item_age, item_state_mode) select ?, coalesce(max(pos), 0)+1, ?, ?, ?, ? from feedcollections
+ insert into feeds(group_id, pos, name, url, auth_user, auth_password, internal_browser, update_interval, max_item_age, item_state_mode)
+ select ?, coalesce(max(pos), 0)+1, ?, ?, ?, ?, ?, ?, ?, ? from feeds
""".trimIndent(), Statement.RETURN_GENERATED_KEYS).use { stmt ->
stmt.setInt(1, parent.id)
stmt.setString(2, name)
- stmt.setLong(3, updateInterval)
- stmt.setInt(4, maxItemAge)
- stmt.setInt(5, itemStateMode)
+ stmt.setString(3, uri)
+ stmt.setString(4, user)
+ stmt.setString(5, password)
+ stmt.setBoolean(6, internalBrowser)
+ stmt.setLong(7, updateInterval)
+ stmt.setInt(8, maxItemAge)
+ stmt.setInt(9, itemStateMode)
stmt.execute()
stmt.generatedKeys.use { rs ->
if(rs.next()) {
- feedcollectionId = rs.getInt(1)
+ feedId = rs.getInt(1)
} else {
throw Exception("Insert FeedCollection failed")
}
}
}
- feedCol = FeedCollection(feedcollectionId, name)
-
- uris.forEach { uri ->
- connection.prepareStatement("""
- insert into feeds (feedcollection_id, url, auth_user, auth_password, certpath) values
- (?, ?, ?, ?, ?)
- """.trimIndent()).use { stmt ->
- stmt.setInt(1, feedcollectionId)
- stmt.setString(2, uri)
- stmt.setString(3, user)
- stmt.setString(4, password)
- stmt.setString(5, cert)
-
- stmt.execute()
- }
- }
+ feed = Feed(feedId, name, uri)
+ parent.feeds.add(feed)
}
- parent.feeds.add(feedCol)
- return feedCol
+ return feed
}
- public fun updateFeedCollection(
- feed: FeedCollection,
- uris: Collection<String>,
- user: String? = null,
- password: String? = null,
- cert: String? = null)
+ public fun updateFeed(feed: Feed)
{
dataSource.connection.use { conn ->
conn.prepareStatement("""
- update feedcollections set
- internal_browser = ?,
+ update feeds set
name = ?,
+ url = ?,
+ auth_user = ?,
+ auth_password = ?,
+ internal_browser = ?,
update_interval = ?,
max_item_age = ?,
- item_state_mode = ?,
- add_url_param = ?
- where feedcollection_id = ?
+ item_state_mode = ?
+ where feed_id = ?
""".trimIndent()).use { stmt ->
- stmt.setBoolean(1, feed.internalBrowser)
- stmt.setString(2, feed.name)
- stmt.setLong(3, feed.updateInterval)
- stmt.setInt(4, feed.maxItemAge)
- stmt.setInt(5, feed.itemStateMode)
- stmt.setString(6, feed.addUrlParam)
- stmt.setInt(7, feed.id)
+ stmt.setString(1, feed.name)
+ stmt.setString(2, feed.uri)
+ stmt.setString(3, feed.user)
+ stmt.setString(4, feed.password)
+ stmt.setBoolean(5, feed.internalBrowser)
+ stmt.setLong(6, feed.updateInterval)
+ stmt.setInt(7, feed.maxItemAge)
+ stmt.setInt(8, feed.itemStateMode)
+ stmt.setInt(9, feed.id)
stmt.execute()
}
-
- var updateList = true
- // check if the old and new list only contain a single uri
- if(uris.size == 1) {
- conn.prepareStatement("select count(*) from feeds where feedcollection_id = ? and disabled = FALSE").use { stmt ->
- stmt.setInt(1, feed.id)
- stmt.executeQuery().use { rs ->
- if(rs.next() && rs.getInt(1) == 1) {
- updateList = false
- }
- }
- }
- }
-
- if(updateList) {
- // disable all feeds first and then re-activate all feeds from the uri list
- conn.prepareStatement("""
- update feeds set auth_user = ?, auth_password = ?, certpath = ?, disabled = TRUE
- where feedcollection_id = ?
- """.trimIndent()).use { stmt ->
- stmt.setString(1, user)
- stmt.setString(2, password)
- stmt.setString(3, cert)
- stmt.setInt(4, feed.id)
- stmt.execute()
- }
-
- // merge url list
- uris.forEach { uri ->
- conn.prepareStatement("""
- merge into feeds f
- using (select cast(? as int) as feedcollection_id, cast(? as varchar) as url) v
- on (f.feedcollection_id = v.feedcollection_id and f.url = v.url)
- when matched then update set
- f.disabled = false
- when not matched then insert(feedcollection_id, url, auth_user, auth_password, certpath)
- values (v.feedcollection_id, v.url, ?, ?, ?)
- """.trimMargin()).use { stmt ->
- stmt.setInt(1, feed.id)
- stmt.setString(2, uri)
- stmt.setString(3, user)
- stmt.setString(4, password)
- stmt.setString(5, cert)
- stmt.execute()
- }
- }
- } else {
- // just update the single feed
- conn.prepareStatement("""
- update feeds set
- url = ?,
- auth_user = ?,
- auth_password = ?,
- certpath = ?
- where feedcollection_id = ?
- """.trimIndent()).use { stmt ->
- stmt.setString(1, uris.first())
- stmt.setString(2, user)
- stmt.setString(3, password)
- stmt.setString(4, cert)
- stmt.setInt(5, feed.id)
- stmt.execute()
- }
- }
}
}
- public fun getItems(feedCollection: FeedCollection, maxItems: Int) : MutableList<Item> {
+ public fun getItems(feed: Feed, maxItems: Int) : MutableList<Item> {
val items = mutableListOf<Item>()
dataSource.connection.use { conn ->
conn.prepareStatement("""
select I.*, F.URL from items I
inner join feeds F on I.feed_id = F.feed_id
- where F.feedcollection_id = ? order by pub_date desc limit ?
+ where F.feed_id = ? order by pub_date desc limit ?
""".trimIndent()).use { stmt ->
- stmt.setInt(1, feedCollection.id)
+ stmt.setInt(1, feed.id)
stmt.setInt(2, maxItems)
stmt.executeQuery().use { rs ->
while(rs.next()) {
item.guid = rs.getString("guid")
item.contentText = rs.getString("contentText")
item.contentHtml = rs.getString("contentHTML")
- item.feedName = feedCollection.name
+ item.feedName = feed.name
item.feedUrl = rs.getString("URL")
item.isRead = rs.getBoolean("is_read")
item.isBookmark = rs.getBoolean("is_bookmarked")
- item.collection = feedCollection
+ item.collection = feed
items.add(item)
}
}
stmt.executeQuery().use { rs ->
while(rs.next()) {
val id = rs.getInt("feed_id")
- val feedCollectionId = rs.getInt("feedcollection_id")
+ val name = rs.getString("name")
val url = rs.getString("url")
val authUser = rs.getString("auth_user")
val authPassword = rs.getString("auth_password")
val certPath = rs.getString("certpath")
- val feed = Feed(id, feedCollectionId, url)
+ val feed = Feed(id, name, url)
feed.user = authUser
feed.password = authPassword
feed.certpath = certPath
return feeds
}
- public fun getCollectionFeeds(feed: FeedCollection) : MutableList<Feed> {
- val feeds = mutableListOf<Feed>()
+ public fun getFeed(id: Int) : Feed? {
+ var feed: Feed? = null;
dataSource.connection.use { conn ->
conn.prepareStatement("""
- select * from feeds where feedcollection_id = ? and disabled = FALSE
+ select * from feeds where feed_id = ? and disabled = FALSE
""".trimIndent()).use { stmt ->
- stmt.setInt(1, feed.id)
+ stmt.setInt(1, id)
stmt.executeQuery().use { rs ->
while(rs.next()) {
val id = rs.getInt("feed_id")
- val feedCollectionId = rs.getInt("feedcollection_id")
+ val name = rs.getString("name")
val url = rs.getString("url")
val authUser = rs.getString("auth_user")
val authPassword = rs.getString("auth_password")
val certPath = rs.getString("certpath")
- val feed = Feed(id, feedCollectionId, url)
+ feed = Feed(id, name, url)
feed.user = authUser
feed.password = authPassword
feed.certpath = certPath
- feeds.add(feed)
+ break
}
}
}
}
- return feeds
+ return feed
}
+
public fun getGroupFeeds(group: FeedGroup) : MutableList<Feed> {
val feeds = mutableListOf<Feed>()
dataSource.connection.use { conn ->
conn.prepareStatement("""
- select f.* from feeds f
- inner join feedcollections c on f.feedcollection_id = c.feedcollection_id
- where c.group_id = ? and disabled = FALSE
+ select * from feeds
+ where group_id = ? and disabled = FALSE
""".trimIndent()).use { stmt ->
stmt.setInt(1, group.id)
stmt.executeQuery().use { rs ->
while(rs.next()) {
val id = rs.getInt("feed_id")
- val feedCollectionId = rs.getInt("feedcollection_id")
+ val name = rs.getString("name")
val url = rs.getString("url")
val authUser = rs.getString("auth_user")
val authPassword = rs.getString("auth_password")
val certPath = rs.getString("certpath")
- val feed = Feed(id, feedCollectionId, url)
+ val feed = Feed(id, name, url)
feed.user = authUser
feed.password = authPassword
feed.certpath = certPath
return feeds
}
- public fun deleteFeedCollection(feedCollection: FeedCollection) {
+ public fun deleteFeed(feed: Feed) {
dataSource.connection.use { conn ->
conn.prepareStatement("""
- delete from feedcollections where feedcollection_id = ?
+ delete from feeds where feed_id = ?
""".trimIndent()).use { stmt ->
- stmt.setInt(1, feedCollection.id)
+ stmt.setInt(1, feed.id)
stmt.execute()
}
}
}
}
- public fun moveFeedCollections(from: FeedGroup, to: FeedGroup) {
+ public fun moveFeeds(from: FeedGroup, to: FeedGroup) {
dataSource.connection.use { conn ->
// move
conn.prepareStatement("""
- update feedcollections set group_id = ? where group_id = ?
+ update feeds set group_id = ? where group_id = ?
""".trimIndent()).use { stmt ->
stmt.setInt(1, to.id)
stmt.setInt(2, from.id)
dataSource.connection.use { conn ->
conn.prepareStatement("""
- select f.* from feeds f
- inner join feedcollections c on f.feedcollection_id = c.feedcollection_id
- where datediff(ss, coalesce(last_update, '1970-01-01'), now()) + 45 > case when c.update_interval > 0 then c.update_interval else ? end
+ select * from feeds
+ where datediff(ss, coalesce(last_update, '1970-01-01'), now()) + 45 > case when update_interval > 0 then update_interval else ? end
and disabled = FALSE
""".trimIndent()).use { stmt ->
stmt.setInt(1, defaultInterval)
stmt.executeQuery().use { rs ->
while(rs.next()) {
val id = rs.getInt("feed_id")
- val feedCollectionId = rs.getInt("feedcollection_id")
+ val name = rs.getString("name")
val url = rs.getString("url")
val authUser = rs.getString("auth_user")
val authPassword = rs.getString("auth_password")
val certPath = rs.getString("certpath")
- val feed = Feed(id, feedCollectionId, url)
+ val feed = Feed(id, name, url)
feed.user = authUser
feed.password = authPassword
feed.certpath = certPath
}
}
- public fun updateFeedReadState(feedCollection: FeedCollection, read: Boolean) {
+ public fun updateFeedReadState(feed: Feed, read: Boolean) {
dataSource.connection.use { conn ->
conn.prepareStatement("""
- update items set is_read = ? where feed_id in (select feed_id from feeds where feedcollection_id = ?)
+ update items set is_read = ? where feed_id = ?
""".trimIndent()).use { stmt ->
stmt.setBoolean(1, read)
- stmt.setInt(2, feedCollection.id)
+ stmt.setInt(2, feed.id)
stmt.execute()
}
}
conn.prepareStatement("""
update items set is_read = ? where feed_id in (
select feed_id from feeds f
- inner join feedcollections c on f.feedcollection_id = c.feedcollection_id
where group_id = ?)
""".trimIndent()).use { stmt ->
stmt.setBoolean(1, read)
dataSource.connection.use { conn ->
conn.prepareStatement("""
select
- datediff(ss, now(), min(dateadd(ss, case when c.update_interval = 0 then ? else c.update_interval end, coalesce(last_update, '1970-01-01')))) as next_update_in
- from feeds f
- inner join feedcollections c on f.feedcollection_id = c.feedcollection_id;
+ datediff(ss, now(), min(dateadd(ss, case when update_interval = 0 then ? else update_interval end, coalesce(last_update, '1970-01-01')))) as next_update_in
+ from feeds;
""".trimIndent()).use { stmt ->
stmt.setInt(1, defaultUpdateInterval)
stmt.executeQuery().use { rs ->
delete from items where item_id in (
select item_id
from (select i.item_id,
- c.name,
+ f.name,
f.feed_id,
- c.max_item_age,
- datediff('dd', coalesce(updated, pub_date), now()) as age,
- case when c.max_item_age > 0 then c.max_item_age else ? end as max_age
+ f.max_item_age,
+ datediff('dd', coalesce(updated, pub_date), now()) as age,
+ case when f.max_item_age > 0 then f.max_item_age else ? end as max_age
from items i
- inner join feeds f on i.feed_id = f.feed_id
- inner join feedcollections c on f.feedcollection_id = c.feedcollection_id
+ inner join feeds f on i.feed_id = f.feed_id
where i.is_bookmarked = false
- and c.max_item_age >= 0)
+ and f.max_item_age >= 0)
where max_age > 0 and age > max_age
)
""".trimIndent()).use { stmt ->
package de.unixwork.rssreader
-import de.unixwork.ui.Text.passwordfield
import de.unixwork.ui.UiObject
import de.unixwork.ui.UiInteger
import de.unixwork.ui.UiList
import de.unixwork.ui.UiString
-import de.unixwork.ui.UiText
import de.unixwork.ui.kotlin.*
-import de.unixwork.ui.kotlin.openFileDialog
class FeedConfig(obj: UiObject) {
val window = obj
- var feedCollection: FeedCollection? = null
+ var feed: Feed? = null
val groups: UiList<FeedGroup>
val name: UiString
- val urls: UiText
+ val uri: UiString
val user: UiString
val password: UiString
val cert: UiString
init {
groups = window.list<FeedGroup>()
name = window.string()
- urls = window.text()
+ uri = window.string()
readstatus = window.list()
user = window.string()
password = window.string()
textfield(value = name, hexpand = true, colspan = 2)
}
row {
- rlabel("URLs", overrideDefaults = true, hfill = true) // overrideDefaults for disabling default vfill
- textarea(value = urls, hexpand = true, vexpand = true, vfill = true, colspan = 2, styleClass = "ui-entry-box")
+ rlabel("URI")
+ textfield(value = uri, hexpand = true, colspan = 2)
}
}
}
groups.selectedIndex = groups.indexOf(it)
}
- feedCollection?.let { initUI(it) }
+ feed?.let { initUI(it) }
}
- private fun initUI(feed: FeedCollection) {
+ private fun initUI(feed: Feed) {
name.setString(feed.name)
readstatus.selectedIndex = feed.itemStateMode
when(feed.maxItemAge) {
maxItemAge.setIntValue(feed.maxItemAge)
}
- val feeds = Database.getCollectionFeeds(feed)
- val uris = feeds.map { it.uri }.joinToString("\n")
+ uri.setString(feed.uri)
- urls.setText(uris)
-
- if(feeds.isNotEmpty()) {
- user.setString(feeds[0].user)
- password.setString(feeds[0].password)
- }
+ user.setString(feed.user)
+ password.setString(feed.password)
}
- fun addFeed() {
+ fun addFeed() : Boolean {
val parent = groups.selected
val feedName = name.toString()
- val urlStr = urls.toString()
- val uris = urlStr.split("\n").map { it.trim() }.filter { it.isNotBlank() }
+ val uri = uri.toString()
var itemStateMode = readstatus.selectedIndex
val internalBrowser = itemContent.selectedIndex == 1
var autoDelete = autoDeleteOptions.selectedIndex
var maxItemAge = maxItemAge.intValue()
var updateIntv = updateInterval.longValue()
+
+ if(feedName.isBlank()) {
+ return false
+ }
+
if(!customUpdateInterval.booleanValue()) {
updateIntv = 0
}
if(itemStateMode < 0 || itemStateMode > 2) {
itemStateMode = 0
}
- println("groupSel: ${groups.selectedIndex}, feedName: $feedName, urlStr: $urlStr")
+ println("groupSel: ${groups.selectedIndex}, feedName: $feedName, uri: $uri")
var u:String? = user.toString()
var p:String? = password.toString()
parent?.let {
FeedConfig.PreviousGroup = it
try {
- val feedCol = Database.newFeeds(
+ val feedCol = Database.newFeed(
parent = it,
name = feedName,
- uris = uris,
+ uri = uri,
user = u,
password = p,
cert = null, //cert.toString(),
e.printStackTrace()
}
}
+
+ return true
}
public fun updateFeed() {
val feedName = name.toString()
- val urlStr = urls.toString()
+ val urlStr = uri.toString()
val uris = urlStr.split("\n").map { it.trim() }.filter { it.isNotBlank() }
var itemStateMode = readstatus.selectedIndex
val internalBrowser = itemContent.selectedIndex == 1
p = null
}
- feedCollection?.let {
+ feed?.let {
it.name = feedName
it.updateInterval = updateIntv
it.itemStateMode = itemStateMode
it.internalBrowser = internalBrowser
it.maxItemAge = maxItemAge
+ it.user = u
+ it.password = p
try {
- Database.updateFeedCollection(it, uris, u, p, null)
+ Database.updateFeed(it)
} catch (e: Exception) {
e.printStackTrace()
}