#curl https://www.tidetimes.org.uk/exmouth-dock-tide-times-20190101 | grep -E -o ">((High|Low)|([0-9]+:[0-9]+)|([0-9]+\.[0-9]+m))" import i3bar_base import std/re import std/httpclient import std/os import std/json import std/times import std/threadpool import std/osproc const url = "https://www.tidetimes.org.uk/%LOC-tide-times" const loc = "exmouth-dock" const icon: string = "🌊" type Tide = ref object State: string Time: string Height: string Tomorrow: bool TideList = ref object Tides: seq[Tide] LastUpdated: DateTime proc sortTides(tides: seq[Tide]): seq[Tide] = let timenow = now() var reltides: seq[Tide] var count = 0 for tide in tides: if timenow.format("HH:MM") <= tide.Time or tide.Tomorrow: reltides.add(tide) count += 1 if count >= 2: break return reltides proc getTideData(gettomorrow: bool = false): seq[Tide] = var tides: seq[Tide] let fnd = re">((High|Low)|([0-9]+:[0-9]+)|([0-9]+\.[0-9]+m))" var client = newHttpClient() var link = replace(url,re"\%LOC",loc) if gettomorrow: let tomdate = now() + initTimeInterval(days = 1) link &= "-" & tomdate.format("yyyyMMdd") try: let data = client.getContent(link) let times = findAll(data,fnd) var tide: Tide var count: int = 0 for time in times: let l = len(time) - 1 if time == ">High" or time == ">Low": tide = Tide() tide.State = time[1..l] count = 1 continue else: count += 1 if count == 2: tide.Time = time[1..l] elif count == 3: tide.Height = time[1..l] if gettomorrow: tide.Tomorrow = true tides.add(tide) except: sleep(5000) return getTideData(false) if not gettomorrow: let tomtides = getTideData(true) for tide in tomtides: tides.add(tide) return tides proc getDesign(tides: seq[Tide]): i3barData = var size = "" if len(tides) > 1: size = "small" let text = icon & tides[0].State[0] & " " & tides[0].Time & " " & tides[0].Height & "\r" & icon & tides[1].State[0] & " " & tides[1].Time & " " & tides[1].Height let t2 = "" & text & "" var data = newi3barData() data.full_text = t2 data.border = black return data proc getTides() {.gcsafe.}= var mytides = TideList() var last_data = "" while true: if len(mytides.Tides) == 0 or mytides.LastUpdated < now() - initTimeInterval(hours = 1): mytides.Tides = getTideData() mytides.LastUpdated = now() let data = getDesign(sortTides(mytides.Tides)) if $data != last_data: outputJSON(data) last_data = $data sleep(10000) proc await_click_info() = while true: let input = parseInput() case input.button: of 1: let state = execCmd("xdg-open " & replace(url,re"\%LOC",loc)) else: let no = false proc main() = spawn getTides() spawn await_click_info() sync() main()