~reesmichael1/roman

ref: 936ef3138ad86e28536ce252d4f10c02e045759e roman/src/romanpkg/subscriptions.nim -rw-r--r-- 3.7 KiB View raw
936ef313Michael Rees Add option for using nim-html2text 2 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import algorithm
import os
import parsecsv
import strutils

import errors
import feeds
import paths
import termask

from types import FeedKind, Subscription


proc newSubscription*(name, url: string, kind: FeedKind): Subscription {.
    raises: [].} =
  Subscription(name: name, url: url, feedKind: kind)


proc getSubscriptions*(): seq[Subscription] {.raises: [RomanError].} =
  let subsFilePath = getSubsFilePath()
  if not existsFile(subsFilePath):
    initConfigDir()
    return
  try:
    var p: CsvParser
    p.open(subsFilePath)
    while p.readRow():
      if p.row.len > 0 and p.row[0].len > 0:
        if p.row[0][0] == '#':
          continue
      if p.row.len != 3:
        raise newException(RomanError,
          "bad line in subscriptions file: " & $p.row)
      var kind: FeedKind
      case p.row[2]:
        of "rss":
          kind = RSS
        of "atom":
          kind = Atom
        else:
          raise newException(RomanError,
            "unrecognized type field in subscriptions file: " & p.row[2])

      result.add(newSubscription(p.row[0], p.row[1], kind))

    result.sort(proc(a, b: Subscription): int = cmpIgnoreCase(a.name, b.name))
  except:
    raise newException(RomanError, getCurrentExceptionMsg())


proc subscriptionToLine(sub: Subscription): string {.raises: [RomanError].} =
  var kind: string
  case sub.feedKind:
  of RSS:
    kind = "rss"
  of Atom:
    kind = "atom"
  of Unknown:
    raise newException(RomanError, "unknown feed type")
  return sub.name & "," & sub.url & "," & kind


proc addFullSubscriptionToSubsFile(subscription: Subscription) {.raises: [RomanError].} =
  try:
    let subs = getSubscriptions()
    if subscription in subs:
      raise newException(RomanError,
        "you are already subscribed to " & subscription.url & "!")
    var f: File
    let filename = getSubsFilePath()
    if f.open(filename, fmAppend):
      defer: f.close()
      f.writeLine(subscriptionToLine(subscription))
  except IOError as e:
    raise newException(RomanError, e.msg)


proc addSubscriptionToSubsFile*(url: string, feedKind: FeedKind) {.
    raises: [RomanError].} =
  let feed = getFeed(newSubscription("", url, feedKind))
  let subscription = newSubscription(feed.title, url, feed.kind)
  addFullSubscriptionToSubsFile(subscription)


proc subscriptionFromLine(line: string): Subscription {.raises: [RomanError].} =
  let fields = line.split(",")
  result.name = fields[0]
  result.url = fields[1]
  case fields[2]
  of "rss": result.feedKind = FeedKind.RSS
  of "atom": result.feedKind = FeedKind.Atom
  else: raise newException(RomanError, "invalid feed type: " & fields[2])


proc removeSubscriptionFromSubsFile*(sub: Subscription) {.
    raises: [RomanError].} =
  try:
    let filename = getSubsFilePath()
    let content = filename.readFile()
    let subsLines = content.splitLines()
    var kind: string
    case sub.feedKind:
    of RSS:
      kind = "rss"
    of Atom:
      kind = "atom"
    of Unknown:
      raise newException(RomanError,
        "trying to save subscription without knowing feed type")
    var f: File
    if f.open(filename, fmWrite):
      defer: f.close()
      for line in subsLines:
        if line.len > 0:
          let s = subscriptionFromLine(line)
          if s != sub:
            f.writeLine(line)
  except IOError as e:
    raise newException(RomanError,
      "could not open subscriptions file: " & e.msg)


proc editSubscriptionTitle*(sub: Subscription) {.raises: [RomanError].} =
  let newName = askUserForInput("Enter new name (empty to go back): ", sub.name)
  if newName == "":
    return
  let newSub = newSubscription(newName, sub.url, sub.feedKind)
  removeSubscriptionFromSubsFile(sub)
  addFullSubscriptionToSubsFile(newSub)