First code import
This commit is contained in:
parent
c47644d63c
commit
73ca0395d6
23
README.md
23
README.md
@ -1,3 +1,24 @@
|
|||||||
# presto2gemini
|
# presto2gemini
|
||||||
|
|
||||||
Download solar storm alerts from the Presto service and converts them into gemtext (text/gemini) to be served via Gemini.
|
Download [solar storm](https://en.wikipedia.org/wiki/Solar_storm) alerts from the [Presto service](http://www.sidc.be/products/presto/) and converts them
|
||||||
|
into gemtext (`text/gemini`) to be served via
|
||||||
|
[Gemini](https://en.wikipedia.org/wiki/Gemini_(protocol)).
|
||||||
|
|
||||||
|
The result can be seen (if you have a Gemini browser( [on my Gemini capsule](gemini://gemini.bortzmeyer.org/presto/).
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Download the program, Be sure you have the [Python requests
|
||||||
|
library](http://python-requests.org/) then run the program periodically, for instance through
|
||||||
|
cron:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Solar alerts
|
||||||
|
33 3,7,11,15,19,23 * * * /path/to/program/presto2gemini.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Technical details
|
||||||
|
|
||||||
|
We start from plain text files like [this
|
||||||
|
alert](http://www.sidc.be/archive/product/presto/2020/12/13) since
|
||||||
|
Presto alerts are not available in a structured format.
|
||||||
|
178
presto2gemini.py
Executable file
178
presto2gemini.py
Executable file
@ -0,0 +1,178 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""A program to retrieve Presto solar storm alerts
|
||||||
|
<http://www.sidc.be/products/presto/> and transform them to gemtext
|
||||||
|
<https://gemini.circumlunar.space/>.
|
||||||
|
|
||||||
|
Run it from cron from time to time.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Standard library
|
||||||
|
import getopt
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
# Other libraries
|
||||||
|
# http://python-requests.org/
|
||||||
|
import requests
|
||||||
|
|
||||||
|
PRESTO_URL = "http://www.sidc.be/archive/product/presto"
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
date = time.strftime("%Y-%m-%d", time.gmtime(time.time()))
|
||||||
|
dest_dir = "/var/gemini/presto"
|
||||||
|
raw_file_dir = "/home/stephane/Gemini/PrestoAlert/raw-files"
|
||||||
|
verbose = False
|
||||||
|
index = True
|
||||||
|
force_index = False
|
||||||
|
input = None
|
||||||
|
|
||||||
|
def usage(msg=None):
|
||||||
|
print("Usage: %s [--date YYYY-MM-DD] [--destination STRING] [--verbose]" % sys.argv[0], file=sys.stderr)
|
||||||
|
if msg is not None:
|
||||||
|
print(msg, file=sys.stderr)
|
||||||
|
|
||||||
|
def create_index(gem_dir, raw_dir):
|
||||||
|
f = open("%s%s" % (gem_dir, "index.gmi"), "w")
|
||||||
|
print("""# List of Presto solar storms alerts
|
||||||
|
|
||||||
|
From the alerts sent by SIDC (Solar Influences Data analysis Center).
|
||||||
|
|
||||||
|
=> http://www.sidc.be/products/presto/ SIDC Presto reference site
|
||||||
|
=> https://en.wikipedia.org/wiki/Solar_storm Wikipedia on solar storms
|
||||||
|
|
||||||
|
""", file=f)
|
||||||
|
files = []
|
||||||
|
for file in os.listdir(raw_dir):
|
||||||
|
files.append(file)
|
||||||
|
sorted_files = sorted(files, reverse=True)
|
||||||
|
fs = open("%s%s.txt" % (gem_dir, sorted_files[0]), "r")
|
||||||
|
print("""
|
||||||
|
Last alert:
|
||||||
|
|
||||||
|
%s
|
||||||
|
""" % fs.read(), file=f)
|
||||||
|
fs.close()
|
||||||
|
for file in sorted(files, reverse=True):
|
||||||
|
print("=> %s.gmi Alert of %s" % (file, file), file=f)
|
||||||
|
|
||||||
|
print("""
|
||||||
|
## Legal and contact
|
||||||
|
|
||||||
|
### This Gemini mirror
|
||||||
|
|
||||||
|
Maintained by Stéphane Bortzmeyer stephane+gemini@bortzmeyer.org from the SIDC data.
|
||||||
|
|
||||||
|
### SIDC - Solar Influences Data analysis Center - RWC Belgium
|
||||||
|
|
||||||
|
Royal Observatory of Belgium
|
||||||
|
|
||||||
|
=> http://www.sidc.be/ Website
|
||||||
|
|
||||||
|
E-mail sidc-support@oma.be
|
||||||
|
|
||||||
|
=> http://www.astro.oma.be/common/internet/en/data-policy-en.pdf Intellectual Property Rights
|
||||||
|
=> http://www.astro.oma.be/common/internet/en/disclaimer-en.pdf Liability Disclaimer
|
||||||
|
=> http://www.astro.oma.be/common/internet/en/privacy-policy-en.pdf Use and processing of your personal information
|
||||||
|
""", file=f)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
try:
|
||||||
|
optlist, args = getopt.getopt (sys.argv[1:], "d:vi",
|
||||||
|
["date=", "help", "verbose",
|
||||||
|
"force-index", "no-index",
|
||||||
|
"destination=", "source=", "input="])
|
||||||
|
for option, value in optlist:
|
||||||
|
if option == "--help" or option == "-h":
|
||||||
|
usage()
|
||||||
|
sys.exit(0)
|
||||||
|
elif option == "--date" or option == "-d":
|
||||||
|
date = value # TODO check the syntax?
|
||||||
|
elif option == "--destination":
|
||||||
|
dest_dir = value
|
||||||
|
elif option == "--source":
|
||||||
|
raw_file_dir = value
|
||||||
|
elif option == "--verbose" or option == "-v":
|
||||||
|
verbose = True
|
||||||
|
elif option == "--force-index" or option == "-i":
|
||||||
|
force_index = True
|
||||||
|
elif option == "--no-index":
|
||||||
|
index = False
|
||||||
|
elif option == "--input":
|
||||||
|
input = value
|
||||||
|
else:
|
||||||
|
# Should never occur, it is trapped by getopt
|
||||||
|
usage("Unknown option %s" % option)
|
||||||
|
except getopt.error as reason:
|
||||||
|
usage(reason)
|
||||||
|
sys.exit(1)
|
||||||
|
if len(args) != 0:
|
||||||
|
usage()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
urlpath = date.replace("-", "/")
|
||||||
|
url = "%s/%s" % (PRESTO_URL, urlpath)
|
||||||
|
if not raw_file_dir.endswith("/"):
|
||||||
|
raw_file_dir += "/"
|
||||||
|
if not dest_dir.endswith("/"):
|
||||||
|
dest_dir += "/"
|
||||||
|
input_ok = False
|
||||||
|
if input is None:
|
||||||
|
r = requests.get(url, allow_redirects = False)
|
||||||
|
if r.status_code == 200 and r.text != "" and r.text != "\r\n" and r.text != "\n": # Yes,
|
||||||
|
# when there is no alert, they reply with 200 and an empty file :-(
|
||||||
|
raw = open("%s%s" % (raw_file_dir, date), "w")
|
||||||
|
print(r.text, file=raw)
|
||||||
|
raw.close()
|
||||||
|
input_ok = True
|
||||||
|
else:
|
||||||
|
shutil.copyfile(input, "%s%s" % (raw_file_dir, date))
|
||||||
|
input_ok = True
|
||||||
|
if input_ok:
|
||||||
|
gemfile = open ("%s%s.gmi" % (dest_dir, date), "w")
|
||||||
|
txtfile = open ("%s%s.txt" % (dest_dir, date), "w")
|
||||||
|
raw = open("%s%s" % (raw_file_dir, date), "r")
|
||||||
|
print("""
|
||||||
|
# Solar alert
|
||||||
|
|
||||||
|
""", file=gemfile)
|
||||||
|
for line in raw.readlines():
|
||||||
|
line=line[:-1] # Chop end-of-line
|
||||||
|
if re.search("^\s*#", line):
|
||||||
|
continue # Ignore comments
|
||||||
|
else:
|
||||||
|
match = re.search("^\s*:([a-zA-Z]+):\s*(.*)", line)
|
||||||
|
if match:
|
||||||
|
if match.group(1) == "Issued":
|
||||||
|
issued = match.group(2)
|
||||||
|
print("""
|
||||||
|
Issued on %s
|
||||||
|
|
||||||
|
""" % issued, file=gemfile)
|
||||||
|
print("""
|
||||||
|
Issued on %s
|
||||||
|
|
||||||
|
""" % issued, file=txtfile)
|
||||||
|
continue # Ignore other metadata
|
||||||
|
else:
|
||||||
|
print(line, file=gemfile, end=" ")
|
||||||
|
print(line, file=txtfile, end=" ")
|
||||||
|
if line == "":
|
||||||
|
print("", file=gemfile)
|
||||||
|
print("", file=txtfile)
|
||||||
|
print("""
|
||||||
|
|
||||||
|
=> %s Reference for this alert
|
||||||
|
=> /presto All Presto solar alerts
|
||||||
|
""" % url, file=gemfile)
|
||||||
|
raw.close()
|
||||||
|
gemfile.close()
|
||||||
|
txtfile.close()
|
||||||
|
if index:
|
||||||
|
create_index(dest_dir, raw_file_dir)
|
||||||
|
elif force_index and index:
|
||||||
|
create_index(dest_dir, raw_file_dir)
|
Loading…
x
Reference in New Issue
Block a user