Add support for tags
This commit is contained in:
parent
afeaa8707b
commit
5135186717
4 changed files with 302 additions and 19 deletions
|
@ -211,6 +211,22 @@ def create_tables(db_file):
|
|||
);
|
||||
"""
|
||||
)
|
||||
feeds_tags_table_sql = (
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS feeds_tags (
|
||||
id INTEGER NOT NULL,
|
||||
feed_id INTEGER NOT NULL,
|
||||
tag_id INTEGER NOT NULL,
|
||||
FOREIGN KEY ("feed_id") REFERENCES "feeds" ("id")
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY ("tag_id") REFERENCES "tags" ("id")
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
"""
|
||||
)
|
||||
# TODO
|
||||
# Consider parameter unique:
|
||||
# entry_id TEXT NOT NULL UNIQUE,
|
||||
|
@ -246,6 +262,15 @@ def create_tables(db_file):
|
|||
);
|
||||
"""
|
||||
)
|
||||
tags_table_sql = (
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS tags (
|
||||
id INTEGER NOT NULL,
|
||||
tag TEXT NOT NULL UNIQUE,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
"""
|
||||
)
|
||||
cur = conn.cursor()
|
||||
# cur = get_cursor(db_file)
|
||||
cur.execute(archive_table_sql)
|
||||
|
@ -254,10 +279,12 @@ def create_tables(db_file):
|
|||
cur.execute(feeds_state_table_sql)
|
||||
cur.execute(feeds_properties_table_sql)
|
||||
cur.execute(feeds_rules_table_sql)
|
||||
cur.execute(feeds_tags_table_sql)
|
||||
cur.execute(filters_table_sql)
|
||||
# cur.execute(statistics_table_sql)
|
||||
cur.execute(settings_table_sql)
|
||||
cur.execute(status_table_sql)
|
||||
cur.execute(tags_table_sql)
|
||||
|
||||
|
||||
def get_cursor(db_file):
|
||||
|
@ -598,7 +625,8 @@ async def remove_feed_by_index(db_file, ix):
|
|||
# cur.execute(sql, par)
|
||||
sql = (
|
||||
"""
|
||||
DELETE FROM feeds
|
||||
DELETE
|
||||
FROM feeds
|
||||
WHERE id = ?
|
||||
"""
|
||||
)
|
||||
|
@ -606,6 +634,231 @@ async def remove_feed_by_index(db_file, ix):
|
|||
cur.execute(sql, par)
|
||||
|
||||
|
||||
def get_tags_by_feed_id(db_file, feed_id):
|
||||
"""
|
||||
Get tags of given feed.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
db_file : str
|
||||
Path to database file.
|
||||
feed_id : str
|
||||
Feed ID.
|
||||
|
||||
Returns
|
||||
-------
|
||||
result : list
|
||||
List of tags.
|
||||
"""
|
||||
with create_connection(db_file) as conn:
|
||||
cur = conn.cursor()
|
||||
sql = (
|
||||
"""
|
||||
SELECT tags.tag
|
||||
FROM tags
|
||||
INNER JOIN feeds_tags ON tags.id = feeds_tags.tag_id
|
||||
INNER JOIN feeds ON feeds.id = feeds_tags.feed_id
|
||||
WHERE feeds.id = ?;
|
||||
"""
|
||||
)
|
||||
par = (feed_id,)
|
||||
result = cur.execute(sql, par).fetchall()
|
||||
return result
|
||||
|
||||
|
||||
async def set_feed_id_and_tag_id(db_file, feed_id, tag_id):
|
||||
"""
|
||||
Set Feed ID and Tag ID.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
db_file : str
|
||||
Path to database file.
|
||||
feed_id : str
|
||||
Feed ID
|
||||
tag_id : str
|
||||
Tag ID
|
||||
"""
|
||||
async with DBLOCK:
|
||||
with create_connection(db_file) as conn:
|
||||
cur = conn.cursor()
|
||||
sql = (
|
||||
"""
|
||||
INSERT
|
||||
INTO feeds_tags(
|
||||
feed_id, tag_id)
|
||||
VALUES(
|
||||
:feed_id, :tag_id)
|
||||
"""
|
||||
)
|
||||
par = {
|
||||
"feed_id": feed_id,
|
||||
"tag_id": tag_id
|
||||
}
|
||||
cur.execute(sql, par)
|
||||
|
||||
|
||||
def get_tag_id(db_file, tag):
|
||||
"""
|
||||
Get ID of given tag. Check whether tag exist.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
db_file : str
|
||||
Path to database file.
|
||||
tag : str
|
||||
Tag.
|
||||
|
||||
Returns
|
||||
-------
|
||||
ix : str
|
||||
Tag ID.
|
||||
"""
|
||||
with create_connection(db_file) as conn:
|
||||
cur = conn.cursor()
|
||||
sql = (
|
||||
"""
|
||||
SELECT id
|
||||
FROM tags
|
||||
WHERE tag = ?
|
||||
"""
|
||||
)
|
||||
par = (tag,)
|
||||
ix = cur.execute(sql, par).fetchone()
|
||||
return ix
|
||||
|
||||
|
||||
def is_tag_id_associated(db_file, tag_id):
|
||||
"""
|
||||
Check whether tag_id is associated with any feed.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
db_file : str
|
||||
Path to database file.
|
||||
tag_id : str
|
||||
Tag ID.
|
||||
|
||||
Returns
|
||||
-------
|
||||
tag_id : str
|
||||
Tag ID.
|
||||
"""
|
||||
with create_connection(db_file) as conn:
|
||||
cur = conn.cursor()
|
||||
sql = (
|
||||
"""
|
||||
SELECT tag_id
|
||||
FROM feeds_tags
|
||||
WHERE tag_id = :tag_id
|
||||
"""
|
||||
)
|
||||
par = {
|
||||
"tag_id": tag_id
|
||||
}
|
||||
tag_id = cur.execute(sql, par).fetchone()
|
||||
return tag_id
|
||||
|
||||
|
||||
async def delete_tag_by_index(db_file, ix):
|
||||
async with DBLOCK:
|
||||
with create_connection(db_file) as conn:
|
||||
cur = conn.cursor()
|
||||
sql = (
|
||||
"""
|
||||
DELETE
|
||||
FROM tags
|
||||
WHERE id = :id
|
||||
"""
|
||||
)
|
||||
par = {
|
||||
"id": ix
|
||||
}
|
||||
cur.execute(sql, par)
|
||||
|
||||
|
||||
def is_tag_id_of_feed_id(db_file, tag_id, feed_id):
|
||||
"""
|
||||
Check whether given tag is related with given feed.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
db_file : str
|
||||
Path to database file.
|
||||
feed_id : str
|
||||
Feed ID.
|
||||
tag_id : str
|
||||
Tag ID.
|
||||
|
||||
Returns
|
||||
-------
|
||||
tag_id : str
|
||||
Tag ID.
|
||||
"""
|
||||
with create_connection(db_file) as conn:
|
||||
cur = conn.cursor()
|
||||
sql = (
|
||||
"""
|
||||
SELECT tag_id
|
||||
FROM feeds_tags
|
||||
WHERE tag_id = :tag_id AND feed_id = :feed_id
|
||||
"""
|
||||
)
|
||||
par = {
|
||||
"tag_id": tag_id,
|
||||
"feed_id": feed_id
|
||||
}
|
||||
tag_id = cur.execute(sql, par).fetchone()
|
||||
return tag_id
|
||||
|
||||
|
||||
async def delete_feed_id_tag_id(db_file, feed_id, tag_id):
|
||||
async with DBLOCK:
|
||||
with create_connection(db_file) as conn:
|
||||
cur = conn.cursor()
|
||||
sql = (
|
||||
"""
|
||||
DELETE
|
||||
FROM feeds_tags
|
||||
WHERE tag_id = :tag_id AND feed_id = :feed_id
|
||||
"""
|
||||
)
|
||||
par = {
|
||||
"tag_id": tag_id,
|
||||
"feed_id": feed_id
|
||||
}
|
||||
cur.execute(sql, par)
|
||||
|
||||
|
||||
async def set_new_tag(db_file, tag):
|
||||
"""
|
||||
Set new Tag
|
||||
|
||||
Parameters
|
||||
----------
|
||||
db_file : str
|
||||
Path to database file.
|
||||
tag : str
|
||||
Tag
|
||||
"""
|
||||
async with DBLOCK:
|
||||
with create_connection(db_file) as conn:
|
||||
cur = conn.cursor()
|
||||
sql = (
|
||||
"""
|
||||
INSERT
|
||||
INTO tags(
|
||||
tag)
|
||||
VALUES(
|
||||
:tag)
|
||||
"""
|
||||
)
|
||||
par = {
|
||||
"tag": tag
|
||||
}
|
||||
cur.execute(sql, par)
|
||||
|
||||
|
||||
async def get_feed_id_and_name(db_file, url):
|
||||
"""
|
||||
Get Id and Name of feed.
|
||||
|
@ -1112,7 +1365,8 @@ async def delete_archived_entry(cur, ix):
|
|||
"""
|
||||
sql = (
|
||||
"""
|
||||
DELETE FROM archive
|
||||
DELETE
|
||||
FROM archive
|
||||
WHERE id = ?
|
||||
"""
|
||||
)
|
||||
|
@ -1469,7 +1723,8 @@ async def maintain_archive(db_file, limit):
|
|||
if difference > 0:
|
||||
sql = (
|
||||
"""
|
||||
DELETE FROM archive
|
||||
DELETE
|
||||
FROM archive
|
||||
WHERE id
|
||||
IN (
|
||||
SELECT id
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
__version__ = '0.1.21'
|
||||
__version_info__ = (0, 1, 21)
|
||||
__version__ = '0.1.22'
|
||||
__version_info__ = (0, 1, 22)
|
||||
|
|
|
@ -621,14 +621,14 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
ftype='text-single',
|
||||
label='Allow list',
|
||||
value=value,
|
||||
desc=('Keywords to allow (comma-separated keywords).'))
|
||||
desc='Keywords to allow (comma-separated keywords).')
|
||||
value = sqlite.get_filter_value(db_file, 'deny')
|
||||
if value: value = str(value[0])
|
||||
form.add_field(var='deny',
|
||||
ftype='text-single',
|
||||
label='Deny list',
|
||||
value=value,
|
||||
desc=('Keywords to deny (comma-separated keywords).'))
|
||||
desc='Keywords to deny (comma-separated keywords).')
|
||||
session['allow_complete'] = True
|
||||
session['has_next'] = False
|
||||
session['next'] = self._handle_filters_complete
|
||||
|
@ -1366,9 +1366,14 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
feed_id = feed_id[0]
|
||||
title = sqlite.get_feed_title(db_file, feed_id)
|
||||
title = title[0]
|
||||
tags_result = sqlite.get_tags_by_feed_id(db_file, feed_id)
|
||||
tags_sorted = sorted(x[0] for x in tags_result)
|
||||
tags = ', '.join(tags_sorted)
|
||||
form['instructions'] = 'Editing subscription #{}'.format(feed_id)
|
||||
else:
|
||||
form['instructions'] = 'Adding subscription'
|
||||
title = ''
|
||||
tags = ''
|
||||
form.add_field(ftype='fixed',
|
||||
value='Properties')
|
||||
form.add_field(var='name',
|
||||
|
@ -1391,11 +1396,14 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
label='ID #',
|
||||
value=feed_id_str)
|
||||
options.addOption(feed_id_str, feed_id_str)
|
||||
form.add_field(var='tags',
|
||||
form.add_field(var='tags_new',
|
||||
ftype='text-single',
|
||||
# ftype='text-multi',
|
||||
label='Tags',
|
||||
value='')
|
||||
desc='Comma-separated tags.',
|
||||
value=tags)
|
||||
form.add_field(var='tags_old',
|
||||
ftype='hidden',
|
||||
value=tags)
|
||||
form.add_field(ftype='fixed',
|
||||
value='Options')
|
||||
options = form.add_field(var='priority',
|
||||
|
@ -1443,8 +1451,32 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
await sqlite.set_enabled_status(db_file, feed_id, enabled_status)
|
||||
name = values['name']
|
||||
await sqlite.set_feed_title(db_file, feed_id, name)
|
||||
values['priority']
|
||||
values['tags']
|
||||
priority = values['priority']
|
||||
tags_new = values['tags_new']
|
||||
tags_old = values['tags_old']
|
||||
# Add new tags
|
||||
for tag in tags_new.split(','):
|
||||
tag = tag.strip()
|
||||
if not tag:
|
||||
continue
|
||||
tag_id = sqlite.get_tag_id(db_file, tag)
|
||||
if not tag_id:
|
||||
await sqlite.set_new_tag(db_file, tag)
|
||||
tag_id = sqlite.get_tag_id(db_file, tag)
|
||||
tag_id = tag_id[0]
|
||||
if not sqlite.is_tag_id_of_feed_id(db_file, tag_id, feed_id):
|
||||
await sqlite.set_feed_id_and_tag_id(db_file, feed_id, tag_id)
|
||||
# Remove tags that were not submitted
|
||||
for tag in tags_old[0].split(','):
|
||||
tag = tag.strip()
|
||||
if not tag:
|
||||
continue
|
||||
if tag not in tags_new:
|
||||
tag_id = sqlite.get_tag_id(db_file, tag)
|
||||
tag_id = tag_id[0]
|
||||
await sqlite.delete_feed_id_tag_id(db_file, feed_id, tag_id)
|
||||
sqlite.is_tag_id_associated(db_file, tag_id)
|
||||
await sqlite.delete_tag_by_index(db_file, tag_id)
|
||||
# form = self['xep_0004'].make_form('form', 'Subscription')
|
||||
# form['instructions'] = ('📁️ Subscription #{} has been {}'
|
||||
# .format(feed_id, action))
|
||||
|
|
|
@ -39,7 +39,7 @@ from slixfeed.xmpp.muc import XmppGroupchat
|
|||
from slixfeed.xmpp.message import XmppMessage
|
||||
from slixfeed.xmpp.presence import XmppPresence
|
||||
from slixfeed.xmpp.upload import XmppUpload
|
||||
from slixfeed.xmpp.utility import get_chat_type
|
||||
from slixfeed.xmpp.utility import get_chat_type, is_moderator
|
||||
import time
|
||||
|
||||
|
||||
|
@ -81,9 +81,7 @@ async def message(self, message):
|
|||
if (message['muc']['nick'] == self.alias):
|
||||
return
|
||||
jid_full = str(message['from'])
|
||||
alias = jid_full[jid_full.index('/')+1:]
|
||||
role = self.plugin['xep_0045'].get_jid_property(jid, alias, 'role')
|
||||
if role != 'moderator':
|
||||
if not is_moderator(self, jid, jid_full):
|
||||
return
|
||||
|
||||
# NOTE This is an exceptional case in which we treat
|
||||
|
@ -132,9 +130,7 @@ async def message(self, message):
|
|||
# return
|
||||
# approved = False
|
||||
jid_full = str(message['from'])
|
||||
role = self.plugin['xep_0045'].get_jid_property(
|
||||
jid, jid_full[jid_full.index('/')+1:], 'role')
|
||||
if role != 'moderator':
|
||||
if not is_moderator(self, jid, jid_full):
|
||||
return
|
||||
# if role == 'moderator':
|
||||
# approved = True
|
||||
|
|
Loading…
Reference in a new issue