Skip to content

Commit

Permalink
Merge pull request #23 from DriverXX/pr
Browse files Browse the repository at this point in the history
Add support for Nextcloud News v15
  • Loading branch information
BernhardPosselt authored Oct 9, 2020
2 parents e52cdf6 + 64ed3ac commit 7e6df79
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 26 deletions.
29 changes: 19 additions & 10 deletions nextcloud_news_updater/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,26 @@ def __init__(self, feed_id: int, user_id: str) -> None:


class Api:
def parse_feed(self, json_string: str) -> List[Feed]:
"""
Wrapper around json.loads for better error messages
"""
"""API JSON results parser"""

def parse_users(self, json_str: str) -> List[str]:
"""Returns a list of userIDs from JSON data"""
try:
users_dict = json.loads(json_str)
return list(users_dict.keys())
except ValueError:
msg = 'Could not parse the JSON user list: %s' % json_str
raise ValueError(msg)

def parse_feeds(self, json_str: str, userID: str = None) -> List[Feed]:
"""Returns a list of feeds from JSON data"""
try:
feed_json = json.loads(json_string)
return self._parse_json(feed_json)
feeds_json = json.loads(json_str)
return self._parse_feeds_json(feeds_json, userID)
except ValueError:
msg = "Could not parse given JSON: %s" % json_string
msg = 'Could not parse given JSON: %s' % json_str
raise ValueError(msg)

def _parse_json(self, feed_json: Any) -> List[Feed]:
feed_json = feed_json['feeds']
return [Feed(info['id'], info['userId']) for info in feed_json]
def _parse_feeds_json(self, feeds: dict, userID: str) -> List[Feed]:
feeds = feeds['feeds']
return [Feed(info['id'], info['userId']) for info in feeds]
77 changes: 67 additions & 10 deletions nextcloud_news_updater/api/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,57 @@ def run(self, commands: List[str]) -> bytes:


class CliApi(Api):
"""Cli API for Nextcloud News up to v14 (API version 1.2)"""

def __init__(self, config: Config) -> None:
directory = config.url
phpini = config.phpini
if not directory.endswith('/'):
directory += '/'
self.directory = directory
base_command = [config.php, '-f', self.directory + 'occ']
self.base_command = [config.php, '-f', self.directory + 'occ']
if phpini is not None and phpini.strip() != '':
base_command += ['-c', phpini]
self.before_cleanup_command = base_command + [
self.base_command += ['-c', phpini]
self.before_cleanup_command = self.base_command + [
'news:updater:before-update']
self.all_feeds_command = base_command + ['news:updater:all-feeds']
self.update_feed_command = base_command + ['news:updater:update-feed']
self.after_cleanup_command = base_command + [
self.all_feeds_command = self.base_command + [
'news:updater:all-feeds']
self.update_feed_command = self.base_command + [
'news:updater:update-feed']
self.after_cleanup_command = self.base_command + [
'news:updater:after-update']


class CliApiV2(CliApi):
"""Cli API for Nextcloud News up to v14 (API version 2)"""

def _parse_feeds_json(self, feeds: dict, userID: str) -> List[Feed]:
feeds = feeds['updater']
return [Feed(info['feedId'], info['userId']) for info in feeds]


class CliApiV15(CliApi):
"""Cli API for Nextcloud News v15+"""

def __init__(self, config: Config) -> None:
super().__init__(config)
self.all_feeds_command = self.base_command + ['news:feed:list']
self.users_list_command = self.base_command + ['user:list', '--output',
'json']

def _parse_json(self, feed_json: Any) -> List[Feed]:
feed_json = feed_json['updater']
return [Feed(info['feedId'], info['userId']) for info in feed_json]
def _parse_feeds_json(self, feeds_json: Any, userID: str) -> List[Feed]:
if not feeds_json:
return []
return [Feed(info['id'], userID) for info in feeds_json]


def create_cli_api(config: Config) -> CliApi:
if config.apilevel == 'v1-2':
return CliApi(config)
if config.apilevel == 'v2':
return CliApiV2(config)
if config.apilevel == 'v15':
return CliApiV15(config)


class CliUpdateThread(UpdateThread):
Expand All @@ -60,6 +80,16 @@ def update_feed(self, feed: Feed) -> None:
self.cli.run(command)


class CliUpdateThreadV15(CliUpdateThread):
"""Cli Updater for Nextcloud News v15+"""

def update_feed(self, feed: Feed) -> None:
command = self.api.update_feed_command + [feed.user_id,
str(feed.feed_id)]
self.logger.info('Running update command: %s' % ' '.join(command))
self.cli.run(command)


class CliUpdater(Updater):
def __init__(self, config: Config, logger: Logger, api: CliApi,
cli: Cli) -> None:
Expand All @@ -81,9 +111,36 @@ def all_feeds(self) -> List[Feed]:
self.logger.info('Running get all feeds command: %s' %
' '.join(self.api.all_feeds_command))
self.logger.info('Received these feeds to update: %s' % feeds_json)
return self.api.parse_feed(feeds_json)
return self.api.parse_feeds(feeds_json)

def after_update(self) -> None:
self.logger.info('Running after update command: %s' %
' '.join(self.api.after_cleanup_command))
self.cli.run(self.api.after_cleanup_command)


class CliUpdaterV15(CliUpdater):
"""Cli Updater for Nextcloud News v15+"""

def start_update_thread(self, feeds: List[Feed]) -> CliUpdateThread:
return CliUpdateThreadV15(feeds, self.logger, self.api, self.cli)

def all_feeds(self) -> List[Feed]:
self.logger.info('Running get user list command: %s' %
' '.join(self.api.users_list_command))
users_json = self.cli.run(self.api.users_list_command).strip()
users_json = str(users_json, 'utf-8')
users = self.api.parse_users(users_json)

feeds_list = []
for userID in users:
self.logger.info('Running get feeds for user "%s" command: %s' %
(userID, ' '.join(self.api.all_feeds_command)))
cmd = self.api.all_feeds_command + [userID]
feeds_json_bytes = self.cli.run(cmd).strip()
feeds_json = str(feeds_json_bytes, 'utf-8')
self.logger.info('Received these feeds to update for user %s: %s' %
(userID, feeds_json))
feeds_list += self.api.parse_feeds(feeds_json, userID)

return feeds_list
8 changes: 4 additions & 4 deletions nextcloud_news_updater/api/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ def __init__(self, config: Config) -> None:
self.all_feeds_url = '%s/updater/all-feeds' % self.base_url
self.update_url = '%s/updater/update-feed' % self.base_url

def _parse_json(self, feed_json: Any) -> List[Feed]:
feed_json = feed_json['updater']
return [Feed(info['feedId'], info['userId']) for info in feed_json]
def _parse_feeds_json(self, feeds: dict, userID: str) -> List[Feed]:
feeds = feeds['updater']
return [Feed(info['feedId'], info['userId']) for info in feeds]


def create_web_api(config: Config) -> WebApi:
Expand Down Expand Up @@ -82,7 +82,7 @@ def start_update_thread(self, feeds: List[Feed]) -> UpdateThread:
def all_feeds(self) -> List[Feed]:
feeds_json = self.client.get(self.api.all_feeds_url, self.auth)
self.logger.info('Received these feeds to update: %s' % feeds_json)
return self.api.parse_feed(feeds_json)
return self.api.parse_feeds(feeds_json)

def after_update(self) -> None:
self.logger.info(
Expand Down
2 changes: 1 addition & 1 deletion nextcloud_news_updater/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def validate(self, config: Config) -> List[str]:
result += ['Unknown mode: %s' % config.mode]
if config.loglevel not in ['info', 'error']:
result += ['Unknown loglevel: %s' % config.loglevel]
if config.apilevel not in ['v1-2', 'v2']:
if config.apilevel not in ['v1-2', 'v2', 'v15']:
result += ['Unknown apilevel: %s' % config.apilevel]

if config.phpini and not os.path.isabs(config.phpini):
Expand Down
4 changes: 3 additions & 1 deletion nextcloud_news_updater/container.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sys

from nextcloud_news_updater.api.cli import CliUpdater, CliApi, \
from nextcloud_news_updater.api.cli import CliUpdater, CliUpdaterV15, CliApi, \
create_cli_api
from nextcloud_news_updater.api.updater import Updater
from nextcloud_news_updater.api.web import create_web_api, WebApi, \
Expand All @@ -23,6 +23,8 @@ def __init__(self) -> None:
def _create_updater(self, container: BaseContainer) -> Updater:
if container.resolve(Config).is_web():
return container.resolve(WebUpdater)
elif container.resolve(Config).apilevel == 'v15':
return container.resolve(CliUpdaterV15)
else:
return container.resolve(CliUpdater)

Expand Down

0 comments on commit 7e6df79

Please sign in to comment.