text: import base64
  import argparse
  import os
  import sqlite3
  import textwrap
  import sys
  
  from voussoirkit import betterhelp
  from voussoirkit import pipeable
  from voussoirkit import vlogging
  from voussoirkit import interactive
  from voussoirkit import niceprints
  
  import bringrss
  
  log = vlogging.getLogger(__name__, 'import_quiterss')
  
  def import_quiterss_argparse(args):
      bringdb = bringrss.bringdb.BringDB.closest_bringdb()
      if not os.path.isfile(args.feedsdb):
          pipeable.stderr(f'{args.bringdb} is not a file.')
          return 1
  
      message = textwrap.dedent('''
      You should make a backup of your BringRSS database before doing this.
      Do not perform this import more than once. We will not search for duplicate data.
      If you need to try the import again, restore from your backup first.
  
      Only feeds and news are imported. Filters are not. Sorry for the inconvenience.
      ''').strip()
  
      pipeable.stderr()
      pipeable.stderr(niceprints.in_box(message, title='Importing from QuiteRSS'))
  
      if not interactive.getpermission('Are you ready?'):
          return 1
  
      quite_sql = sqlite3.connect(args.feedsdb)
      quite_sql.row_factory = sqlite3.Row
      feed_id_map = {}
      query = '''
      SELECT
          id,
          text,
          description,
          xmlUrl,
          htmlUrl,
          image,
          parentId,
          rowToParent,
          updateIntervalEnable,
          updateInterval,
          updateIntervalType,
          disableUpdate
      FROM feeds;
      '''
      feeds = list(quite_sql.execute(query))
      while feeds:
          feed = feeds.pop(0)
          quite_id = feed['id']
          if feed['parentId'] == 0:
              parent = None
          elif feed['parentId'] in feed_id_map:
              parent = feed_id_map[feed['parentId']]
          else:
              # The parent is probably somewhere else in the list, let's come
              # back to it later.
              feeds.append(feed)
              continue
  
          title = feed['text']
          description = feed['description']
          rss_url = feed['xmlUrl']
          web_url = feed['htmlUrl']
          # rowToParent is zero-indexed, we use 1-index.
          if parent:
              # If the parent has ui_order_rank of 8, then a child with rowToParent
              # of 4 will be 8.0004 and everything will get reassigned later.
              ui_order_rank = parent.ui_order_rank + ((feed['rowToParent'] + 1) / 10000)
          else:
              ui_order_rank = feed['rowToParent'] + 1
  
          if feed['updateIntervalEnable'] == 1 and feed['updateInterval'] > 0:
              if feed['updateIntervalType'] in {1, "1"}:
                  # hours
                  autorefresh_interval = feed['updateInterval'] * 3600
              elif feed['updateIntervalType'] in {0, "0"}:
                  # minutes
                  autorefresh_interval = feed['updateInterval'] * 60
              elif feed['updateIntervalType'] in {-1, "-1"}:
                  # seconds
                  autorefresh_interval = feed['updateInterval']
          else:
              autorefresh_interval = 0
  
          if feed['disableUpdate'] == 1:
              refresh_with_others = False
              autorefresh_interval = min(autorefresh_interval, -1 * autorefresh_interval)
          else:
              refresh_with_others = True
  
          isolate_guids = False
  
          if feed['image']:
              icon = base64.b64decode(feed['image'])
          else:
              icon = None
  
          feed = bringdb.add_feed(
              autorefresh_interval=autorefresh_interval,
              description=description,
              icon=icon,
              isolate_guids=isolate_guids,
              parent=parent,
              refresh_with_others=refresh_with_others,
              rss_url=rss_url,
              title=title,
              ui_order_rank=ui_order_rank,
              web_url=web_url,
          )
          feed_id_map[quite_id] = feed
  
      bringdb.reassign_ui_order_ranks()
  
      query = '''
      SELECT
          feedId,
          guid,
          description,
          title,
          published,
          modified,
          author_name,
          author_uri,
          author_email,
          read,
          comments,
          enclosure_length,
          enclosure_type,
          enclosure_url,
          link_href
      FROM news
      WHERE deleted == 0;
      '''
      newss = list(quite_sql.execute(query))
      for news in newss:
          quite_read = news['read']
  
          authors = [{
              'name': news['author_name'],
              'email': news['author_email'],
              'uri': news['author_uri'],
          }]
          enclosures = [{
              'url': news['enclosure_url'],
              'type': news['enclosure_type'],
              'size': int(news['enclosure_length']) if news.get('enclosure_length') else None
          }]
  
          news = bringdb.add_news(
              authors=authors,
              comments_url=news['comments'],
              enclosures=enclosures,
              feed=feed_id_map[news['feedId']],
              published=news['published'],
              rss_guid=news['guid'],
              text=news['description'],
              title=news['title'],
              updated=news['modified'] or news['published'],
              web_url=news['link_href'],
          )
          if quite_read > 0:
              news.set_read(True)
      bringdb.commit()
  
      return 0
  
  @vlogging.main_decorator
  def main(argv):
      parser = argparse.ArgumentParser(
          description='''
          Import feeds and news from QuiteRSS to BringRSS.
          ''',
      )
      parser.add_argument(
          'feedsdb',
          help='''
          Filepath to the feeds.db in your QuiteRSS folder.
          ''',
      )
      parser.set_defaults(func=import_quiterss_argparse)
  
      return betterhelp.go(parser, argv)
  
  if __name__ == '__main__':
      raise SystemExit(main(sys.argv[1:]))
  