summaryrefslogtreecommitdiffstats
path: root/nwscap.py
blob: 20c0d465df539cd84ff49f529cfc76da2c34350b (plain)
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
130
131
132
133
134
135
136
#!/usr/bin/env python
"""Parse active NOAA NWS CAP advisories and output an ATOM feed"""

__author__ = 'Daniel Washburn'
__copyright__ = 'Copyright (c) 2013-2017'
__license__ = 'http://opensource.org/licenses/BSD-3-Clause'

import cgi
import getopt
import sys
import urllib2
from lxml import etree
from lxml.etree import SubElement

ATOM_URI = 'http://www.w3.org/2005/Atom'
ATOM_NAMESPACE = {'atom': ATOM_URI}
CAP_URI = 'urn:oasis:names:tc:emergency:cap:1.1'
CAP_NAMESPACE = {'cap': CAP_URI}
CAP_SCHEMA_URL = 'http://docs.oasis-open.org/emergency/cap/v1.1/errata/approved/cap.xsd'
CAP_XSLT_URL = 'capatomcustom.xsl'

cap_schema_url = urllib2.urlopen(CAP_SCHEMA_URL)
CAP_SCHEMA = etree.XMLSchema(etree.parse(cap_schema_url))
CAP_XSLT = xslt_transform = etree.XSLT(etree.parse(CAP_XSLT_URL))

ATOM_PARSER = etree.XMLParser(ns_clean=True, remove_comments=True)
CAP_PARSER = etree.XMLParser(ns_clean=True, remove_comments=True,
        remove_blank_text=True, schema=CAP_SCHEMA)

def usage():
    print """nwscap.py [-h] -t (region|zone) -a area

-h|--help		Print this message and exit
-t|--type		Area type. must be either region or zone
-a|--area		The area to report on
"""

try:
    opts, args = getopt.gnu_getopt(sys.argv[1:],
            "ht:a:",
            ["help", "type=", "area="])
except getopt.GetoptError as err:
    print str(err)
    usage()
    sys.exit(2)
area_type=False
area=False
url=False

for o, a in opts:
    if o in ("-h", "--help"):
        usage()
        sys.exit()
    elif o in ("-t", "--type"):
        if a in ("region", "zone"):
            area_type = a
        else:
            print """type must be one of: region, zone"""
            usage()
            sys.exit()
    elif o in ("-a", "--area"):
        area = a
    else:
        assert False, "unhandled option"

if area_type and area:
    if area_type == "region":
        url='https://alerts.weather.gov/cap/' + area + '.php?x=0'
    elif area_type == "zone":
        url='https://alerts.weather.gov/cap/wwaatmget.php?x=' + area + '&y=0'
else:
    print """Both type and area must be specified"""
    usage()
    sys.exit()

feed=urllib2.urlopen(url)
in_feed = etree.parse(feed, ATOM_PARSER)

out_feed = etree.XML('''<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
        <feed xmlns='http://www.w3.org/2005/Atom'/>''')
SubElement(out_feed, 'id').text = "%s" % \
        in_feed.xpath('/atom:feed/atom:id',
        namespaces=ATOM_NAMESPACE)[0].text
SubElement(out_feed, 'updated').text = "%s" % \
        in_feed.xpath('/atom:feed/atom:updated',
        namespaces=ATOM_NAMESPACE)[0].text
out_feed_author = SubElement(out_feed, 'author')
SubElement(out_feed_author, 'name').text = "%s" % \
        in_feed.xpath('/atom:feed/atom:author/atom:name',
        namespaces=ATOM_NAMESPACE)[0].text
SubElement(out_feed, 'title').text = "%s" % \
        in_feed.xpath('/atom:feed/atom:title',
        namespaces=ATOM_NAMESPACE)[0].text
SubElement(out_feed, 'link', href="%s" % \
        in_feed.xpath('/atom:feed/atom:link/@href',
        namespaces=ATOM_NAMESPACE)[0])

# get URLs of active alerts
entry_titles = in_feed.xpath('/atom:feed/atom:entry/atom:title',
        namespaces=ATOM_NAMESPACE)
alert_links=in_feed.xpath('/atom:feed/atom:entry/atom:link/@href',
        namespaces=ATOM_NAMESPACE)

no_alerts_title = 'There are no active watches, warnings or advisories'
if no_alerts_title in entry_titles[0].text:
    alert_links = []

for link in alert_links:
    cap_link=urllib2.urlopen(link)
    cap=etree.parse(cap_link, CAP_PARSER)
    cap_entry = SubElement(out_feed, 'entry')
    SubElement(cap_entry, 'id').text = "%s" % \
            cap.xpath('/cap:alert/cap:identifier',
                namespaces=CAP_NAMESPACE)[0].text

    cap_entry_author = SubElement(cap_entry, 'author')

    SubElement(cap_entry_author, 'name').text = "%s" % \
            cap.xpath('/cap:alert/cap:sender',
                namespaces=CAP_NAMESPACE)[0].text

    SubElement(cap_entry, 'title').text = "%s" % \
            cap.xpath('/cap:alert/cap:info/cap:headline',
                namespaces=CAP_NAMESPACE)[0].text

    SubElement(cap_entry, 'published').text = "%s" % \
            cap.xpath('/cap:alert/cap:sent',
                namespaces=CAP_NAMESPACE)[0].text

    SubElement(cap_entry, 'link', href=link)

    SubElement(cap_entry, "content", type="text/html").text = "%s" % \
            etree.tostring(xslt_transform(cap), pretty_print=True)

out_tree = etree.ElementTree(out_feed)
print(etree.tostring(out_tree, pretty_print=True, method='xml'))