added LICENSE
added README fixed pylint findings added screenshot
This commit is contained in:
parent
116567b979
commit
48d7df5f74
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2022 Michael Clemens, DK1MI
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
60
README.md
60
README.md
|
@ -0,0 +1,60 @@
|
||||||
|
# ColorSpot
|
||||||
|
|
||||||
|
This script is a command line DX cluster client. It adds the following benefits to the default telnet stream:
|
||||||
|
|
||||||
|
* displays the DX station's country
|
||||||
|
* displays the DX station's continent
|
||||||
|
* displays if the DX station uses LotW
|
||||||
|
* downloads your LotW QSL file and marks all lines with countries that need to be confirmed
|
||||||
|
* displays lines in different colors depending on the continent or band (user configurable)
|
||||||
|
|
||||||
|
# Screnshot
|
||||||
|
|
||||||
|
![screenshot](/screenshot.png?raw=true "screenshot")
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
ColorSpot needs Python 3 and the following libraries:
|
||||||
|
|
||||||
|
* colored
|
||||||
|
* requests
|
||||||
|
* Telnet
|
||||||
|
* zipfile
|
||||||
|
|
||||||
|
Furthermore, you need an account at LotW for some of teh features.
|
||||||
|
|
||||||
|
Before installing ColorSpot, please make sure that pip, setuptools and wheel are installed and up-to-date:
|
||||||
|
|
||||||
|
```
|
||||||
|
# python3 -m pip install --upgrade pip setuptools wheel
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, install ColorSpot with pip:
|
||||||
|
|
||||||
|
```
|
||||||
|
# python3 -m pip install colorspot
|
||||||
|
```
|
||||||
|
|
||||||
|
# Updating
|
||||||
|
|
||||||
|
To update colorspot, execute the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
# python3 -m pip install --upgrade colorspot
|
||||||
|
```
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
* execute the application with "colorspot"
|
||||||
|
* colorspot creates a default config file and states its location (e.g. _~/.colorspot.ini_)
|
||||||
|
* adapt _~/.colorspot.ini_ to your needs. Important setting are:
|
||||||
|
* cluster/host and cluster/port: Change this if you want to use another cluster server
|
||||||
|
* cluster/user: Enter here your call sign
|
||||||
|
* lotw/user: Enter here your lotw user name (your call sign)
|
||||||
|
* lotw/password: Enter here your lotw password
|
||||||
|
* lotw/mode: Enter here the mode you would like to filter the QSL download from LotW
|
||||||
|
* execute the application again with "colorspot"
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
see ![LICENSE](LICENSE)
|
243
colorspot.py
243
colorspot.py
|
@ -1,28 +1,49 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# pylint: disable=W1401,C0303
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
+---------------------------------------------------------------------+
|
||||||
|
| |
|
||||||
|
| ___ _ ___ _ |
|
||||||
|
| / __|___| |___ _ _/ __|_ __ ___| |_ |
|
||||||
|
| | (__/ _ \ / _ \ '_\__ \ '_ \/ _ \ _| |
|
||||||
|
| \___\___/_\___/_| |___/ .__/\___/\__| |
|
||||||
|
| -= DK1MI =- |_| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| A colorful cli DX cluster client with an LotW integration |
|
||||||
|
| |
|
||||||
|
| Author: Michael Clemens, DK1MI (colorspot@qrz.is) |
|
||||||
|
| |
|
||||||
|
| Documentation: Please see the README.md file |
|
||||||
|
| License: Please see the LICENSE file |
|
||||||
|
| Repository: https://git.qrz.is/clemens/colorspot |
|
||||||
|
| |
|
||||||
|
+---------------------------------------------------------------------+
|
||||||
|
"""
|
||||||
|
|
||||||
# Infos on colors: https://pypi.org/project/colored/
|
# Infos on colors: https://pypi.org/project/colored/
|
||||||
# Country list extracted from http://www.arrl.org/files/file/dxcclist.txt
|
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import csv
|
import csv
|
||||||
import re
|
import re
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import time as bla
|
|
||||||
from telnetlib import Telnet
|
|
||||||
from colored import fg, bg, attr
|
|
||||||
import configparser
|
|
||||||
from collections import defaultdict
|
|
||||||
import random
|
import random
|
||||||
import requests
|
import os
|
||||||
from os.path import exists
|
from os.path import exists
|
||||||
|
import configparser
|
||||||
import zipfile
|
import zipfile
|
||||||
|
from telnetlib import Telnet
|
||||||
|
import requests
|
||||||
|
from colored import fg, bg, attr
|
||||||
|
|
||||||
class ColorSpot():
|
class ColorSpot():
|
||||||
|
"""ColorSpot class"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
"""initialize things"""
|
||||||
|
|
||||||
self.version = "0.1.0"
|
self.version = "0.1.0"
|
||||||
|
|
||||||
self.print_banner()
|
self.print_banner()
|
||||||
|
@ -37,76 +58,14 @@ class ColorSpot():
|
||||||
self.confirmed_entities = self.get_confirmed_entities()
|
self.confirmed_entities = self.get_confirmed_entities()
|
||||||
|
|
||||||
if self.check_cty:
|
if self.check_cty:
|
||||||
self.cty = list(csv.reader(open(self.config['files']['cty'], "r"), delimiter=","))
|
#self.cty = list(csv.reader(open(self.config['files']['cty'], "r"), delimiter=","))
|
||||||
|
with open(self.config['files']['cty'], encoding='us-ascii') as csvfile:
|
||||||
@staticmethod
|
self.cty = list(csv.reader(csvfile, delimiter=','))
|
||||||
def rnd_col():
|
|
||||||
r = lambda: random.randint(0,255)
|
|
||||||
return'#%02X%02X%02X' % (r(),r(),r())
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def download_file(url, local_filename):
|
|
||||||
with requests.get(url, stream=True) as r:
|
|
||||||
r.raise_for_status()
|
|
||||||
with open(local_filename, 'wb') as f:
|
|
||||||
for chunk in r.iter_content(chunk_size=8192):
|
|
||||||
f.write(chunk)
|
|
||||||
return local_filename
|
|
||||||
|
|
||||||
def check_files(self):
|
|
||||||
# check for lotw qsl information file
|
|
||||||
self.check_lotw_confirmed = exists(self.config['files']['lotw_confirmed'])
|
|
||||||
if not self.check_lotw_confirmed:
|
|
||||||
print("The file " + self.config['files']['lotw_confirmed'] + " is missing.")
|
|
||||||
user = self.config['lotw']['user']
|
|
||||||
password = self.config['lotw']['password']
|
|
||||||
mode = self.config['lotw']['mode']
|
|
||||||
url = "https://lotw.arrl.org/lotwuser/lotwreport.adi?login={}&password={}&qso_query=1&qso_qsl=yes&qso_mode={}&qso_qsldetail=yes&qso_qslsince=1970-01-01".format(user, password, mode)
|
|
||||||
print("Trying to download " + url)
|
|
||||||
file_name = self.download_file(url, self.config['files']['lotw_confirmed'])
|
|
||||||
self.check_lotw_confirmed = exists(self.config['files']['lotw_confirmed'])
|
|
||||||
if self.check_lotw_confirmed:
|
|
||||||
print("File successfully downloaded")
|
|
||||||
else:
|
|
||||||
print("something went wrong while downloading " + url)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# check for cty.csv file
|
|
||||||
self.check_cty = exists(self.config['files']['cty'])
|
|
||||||
if not self.check_cty:
|
|
||||||
url = self.config['files']['cty_url']
|
|
||||||
print("The file " + self.config['files']['cty'] + " is missing.")
|
|
||||||
print("Trying to download " + url)
|
|
||||||
zip_name = self.download_file(url, "bigcty.zip" )
|
|
||||||
with zipfile.ZipFile(zip_name, 'r') as zip_ref:
|
|
||||||
zip_ref.extract("cty.csv")
|
|
||||||
os.remove(zip_name)
|
|
||||||
self.check_cty = exists(self.config['files']['cty'])
|
|
||||||
if self.check_cty:
|
|
||||||
print("File successfully downloaded and extracted.")
|
|
||||||
else:
|
|
||||||
print("something went wrong while downloading " + url)
|
|
||||||
|
|
||||||
# check for lotw user activity file
|
|
||||||
self.check_lotw_activity = exists(self.config['files']['lotw_activity'])
|
|
||||||
if not self.check_lotw_activity:
|
|
||||||
url = self.config['files']['lotw_activity_url']
|
|
||||||
print("The file " + self.config['files']['lotw_activity'] + " is missing.")
|
|
||||||
print("Trying to download " + url)
|
|
||||||
file_name = self.download_file(url, self.config['files']['lotw_activity'])
|
|
||||||
self.check_lotw_activity = exists(self.config['files']['lotw_activity'])
|
|
||||||
if self.check_lotw_activity:
|
|
||||||
print("File successfully downloaded")
|
|
||||||
else:
|
|
||||||
print("something went wrong while downloading " + url)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def print_banner(self):
|
def print_banner(self):
|
||||||
"""print an awesome banner"""
|
"""print an awesome banner"""
|
||||||
ver = self.version
|
|
||||||
# print the banner
|
|
||||||
print(fg(self.rnd_col())+" ___ _ ___ _ ")
|
print(fg(self.rnd_col())+" ___ _ ___ _ ")
|
||||||
print(fg(self.rnd_col())+" / __|___| |___ _ _/ __|_ __ ___| |_ ")
|
print(fg(self.rnd_col())+" / __|___| |___ _ _/ __|_ __ ___| |_ ")
|
||||||
print(fg(self.rnd_col())+" | (__/ _ \ / _ \ '_\__ \ '_ \/ _ \ _|")
|
print(fg(self.rnd_col())+" | (__/ _ \ / _ \ '_\__ \ '_ \/ _ \ _|")
|
||||||
|
@ -115,6 +74,7 @@ class ColorSpot():
|
||||||
print("")
|
print("")
|
||||||
print(attr('reset'))
|
print(attr('reset'))
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def read_config(config, file_name):
|
def read_config(config, file_name):
|
||||||
"""reads the configuration from the config file or
|
"""reads the configuration from the config file or
|
||||||
|
@ -136,7 +96,7 @@ class ColorSpot():
|
||||||
'lotw_activity_url': 'https://lotw.arrl.org/lotw-user-activity.csv'}
|
'lotw_activity_url': 'https://lotw.arrl.org/lotw-user-activity.csv'}
|
||||||
config['lotw'] = {
|
config['lotw'] = {
|
||||||
'user': 'N0CALL',
|
'user': 'N0CALL',
|
||||||
'password': 'XXXXXXXXX',
|
'password': 'CHANGEME',
|
||||||
'mode': 'ssb'}
|
'mode': 'ssb'}
|
||||||
config['band_colors'] = {
|
config['band_colors'] = {
|
||||||
"145": "white",
|
"145": "white",
|
||||||
|
@ -171,17 +131,88 @@ class ColorSpot():
|
||||||
'alert_fg': 'white',
|
'alert_fg': 'white',
|
||||||
'default_bg': 'black'}
|
'default_bg': 'black'}
|
||||||
|
|
||||||
with open(file_name, 'w') as configfile:
|
with open(file_name, 'w', encoding='us-ascii') as configfile:
|
||||||
config.write(configfile)
|
config.write(configfile)
|
||||||
print("\nNo configuration file found. A new configuration file has been created.")
|
print("\nNo configuration file found. A new configuration file has been created.")
|
||||||
print("\nPlease edit the file " + file_name + " and restart the application.\n" )
|
print("\nPlease edit the file " + file_name + " and restart the application.\n" )
|
||||||
sys.exit()
|
sys.exit()
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def rnd_col():
|
||||||
|
"""generates a random color cod ein hex"""
|
||||||
|
rand = lambda: random.randint(0,255)
|
||||||
|
return'#%02X%02X%02X' % (rand(),rand(),rand())
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def download_file(url, local_filename):
|
||||||
|
"""downloads a file via HTTP and saves it to a defined file"""
|
||||||
|
with requests.get(url, stream=True) as request:
|
||||||
|
request.raise_for_status()
|
||||||
|
with open(local_filename, 'wb') as file:
|
||||||
|
for chunk in request.iter_content(chunk_size=8192):
|
||||||
|
file.write(chunk)
|
||||||
|
return local_filename
|
||||||
|
|
||||||
|
|
||||||
|
def check_files(self):
|
||||||
|
"""Checks if all necessary files are in the file system.
|
||||||
|
Downloads all files and unzips them (if necessary)"""
|
||||||
|
# check for lotw qsl information file
|
||||||
|
self.check_lotw_confirmed = exists(self.config['files']['lotw_confirmed'])
|
||||||
|
if not self.check_lotw_confirmed:
|
||||||
|
print("The file " + self.config['files']['lotw_confirmed'] + " is missing.")
|
||||||
|
user = self.config['lotw']['user']
|
||||||
|
password = self.config['lotw']['password']
|
||||||
|
mode = self.config['lotw']['mode']
|
||||||
|
url = "https://lotw.arrl.org/lotwuser/lotwreport.adi?login={}&password={}"\
|
||||||
|
"&qso_query=1&qso_qsl=yes&qso_mode={}&qso_qsldetail=yes&"\
|
||||||
|
"qso_qslsince=1970-01-01".format(user, password, mode)
|
||||||
|
print("Trying to download " + url)
|
||||||
|
self.download_file(url, self.config['files']['lotw_confirmed'])
|
||||||
|
self.check_lotw_confirmed = exists(self.config['files']['lotw_confirmed'])
|
||||||
|
if self.check_lotw_confirmed:
|
||||||
|
print("File successfully downloaded")
|
||||||
|
else:
|
||||||
|
print("something went wrong while downloading " + url)
|
||||||
|
|
||||||
|
# check for cty.csv file
|
||||||
|
self.check_cty = exists(self.config['files']['cty'])
|
||||||
|
if not self.check_cty:
|
||||||
|
url = self.config['files']['cty_url']
|
||||||
|
print("The file " + self.config['files']['cty'] + " is missing.")
|
||||||
|
print("Trying to download " + url)
|
||||||
|
zip_name = self.download_file(url, "bigcty.zip" )
|
||||||
|
with zipfile.ZipFile(zip_name, 'r') as zip_ref:
|
||||||
|
zip_ref.extract("cty.csv")
|
||||||
|
os.remove(zip_name)
|
||||||
|
self.check_cty = exists(self.config['files']['cty'])
|
||||||
|
if self.check_cty:
|
||||||
|
print("File successfully downloaded and extracted.")
|
||||||
|
else:
|
||||||
|
print("something went wrong while downloading " + url)
|
||||||
|
|
||||||
|
# check for lotw user activity file
|
||||||
|
self.check_lotw_activity = exists(self.config['files']['lotw_activity'])
|
||||||
|
if not self.check_lotw_activity:
|
||||||
|
url = self.config['files']['lotw_activity_url']
|
||||||
|
print("The file " + self.config['files']['lotw_activity'] + " is missing.")
|
||||||
|
print("Trying to download " + url)
|
||||||
|
self.download_file(url, self.config['files']['lotw_activity'])
|
||||||
|
self.check_lotw_activity = exists(self.config['files']['lotw_activity'])
|
||||||
|
if self.check_lotw_activity:
|
||||||
|
print("File successfully downloaded")
|
||||||
|
else:
|
||||||
|
print("something went wrong while downloading " + url)
|
||||||
|
|
||||||
|
|
||||||
def get_confirmed_entities(self):
|
def get_confirmed_entities(self):
|
||||||
|
"""Reads the file downlaoded from LotW with all confirmed QSOs,
|
||||||
|
extracts all confirmed DXCCs and puts them into a list"""
|
||||||
ret = []
|
ret = []
|
||||||
#TODO: download file and/or tell user what to do
|
with open(self.config['files']['lotw_confirmed'], encoding='us-ascii') as file:
|
||||||
file = open(self.config['files']['lotw_confirmed'], "r")
|
|
||||||
for row in file:
|
for row in file:
|
||||||
if re.search("<DXCC:", row):
|
if re.search("<DXCC:", row):
|
||||||
dxcc = row.partition(">")[2].lower().rstrip()
|
dxcc = row.partition(">")[2].lower().rstrip()
|
||||||
|
@ -189,10 +220,14 @@ class ColorSpot():
|
||||||
ret.append(dxcc)
|
ret.append(dxcc)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def check_lotw(self, call):
|
def check_lotw(self, call):
|
||||||
|
"""Reads the LotW user activity file and returns the date
|
||||||
|
of the last upload date if a specific call sign"""
|
||||||
ret = ""
|
ret = ""
|
||||||
#TODO: download file and/or tell user what to do
|
#csv_file = csv.reader(open(self.config['files']['lotw_activity'], "r"), delimiter=",")
|
||||||
csv_file = csv.reader(open(self.config['files']['lotw_activity'], "r"), delimiter=",")
|
with open(self.config['files']['lotw_activity'], encoding='us-ascii') as csvfile:
|
||||||
|
csv_file = csv.reader(csvfile, delimiter=',')
|
||||||
#loop through the csv file
|
#loop through the csv file
|
||||||
for row in csv_file:
|
for row in csv_file:
|
||||||
if call == row[0]:
|
if call == row[0]:
|
||||||
|
@ -200,12 +235,15 @@ class ColorSpot():
|
||||||
return ret
|
return ret
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def get_cty_row(self, call):
|
def get_cty_row(self, call):
|
||||||
|
"""Parses all CTY records, tries to find the DXCC entity of a
|
||||||
|
specific call sign and returns the line as a list of strings"""
|
||||||
done = False
|
done = False
|
||||||
while not done:
|
while not done:
|
||||||
for row in self.cty:
|
for row in self.cty:
|
||||||
entities = row[9].replace(";", "").replace("=", "").split(" ")
|
entities = row[9].replace(";", "").replace("=", "").split(" ")
|
||||||
# TODO: schauen ob = davor und match -> als special call anzeigen
|
# TODO: Check if it is a speciall call (=) and mark it in the list
|
||||||
for prefix in entities:
|
for prefix in entities:
|
||||||
if call == prefix:
|
if call == prefix:
|
||||||
return row
|
return row
|
||||||
|
@ -216,14 +254,19 @@ class ColorSpot():
|
||||||
|
|
||||||
|
|
||||||
def get_spots(self):
|
def get_spots(self):
|
||||||
|
"""Connects to the specified telnet dx cluster, performs a login, grabs the
|
||||||
|
output row by row, enriches it with data and colorizes it depending on certain
|
||||||
|
paramaeters, e.g. by band or continent."""
|
||||||
with Telnet(self.config['cluster']['host'], int(self.config['cluster']['port']), \
|
with Telnet(self.config['cluster']['host'], int(self.config['cluster']['port']), \
|
||||||
int(self.config['cluster']['timeout'])) as telnet:
|
int(self.config['cluster']['timeout'])) as telnet:
|
||||||
while True:
|
while True:
|
||||||
line_enc = telnet.read_until(b"\n") # Read one line
|
line_enc = telnet.read_until(b"\n") # Read one line
|
||||||
line = line_enc.decode('ascii')
|
line = line_enc.decode('ascii')
|
||||||
|
# Enters the call sign if requested
|
||||||
if "enter your call" in line:
|
if "enter your call" in line:
|
||||||
b_user = str.encode(self.config['cluster']['user']+"\n")
|
b_user = str.encode(self.config['cluster']['user']+"\n")
|
||||||
telnet.write(b_user)
|
telnet.write(b_user)
|
||||||
|
# Detects the beginning of the stream and generates a header line
|
||||||
elif " Hello " in line:
|
elif " Hello " in line:
|
||||||
print(fg("grey_27") + line + attr("reset"))
|
print(fg("grey_27") + line + attr("reset"))
|
||||||
foreground = "white"
|
foreground = "white"
|
||||||
|
@ -231,20 +274,25 @@ class ColorSpot():
|
||||||
sep = fg("grey_27")+'|'+fg(foreground)
|
sep = fg("grey_27")+'|'+fg(foreground)
|
||||||
row = ["DE", sep, "Freq", sep, "DX", \
|
row = ["DE", sep, "Freq", sep, "DX", \
|
||||||
sep, "Country", sep, "C", sep, "L", sep, "Comment", sep, "Time"]
|
sep, "Country", sep, "C", sep, "L", sep, "Comment", sep, "Time"]
|
||||||
|
|
||||||
print(bg(background) + fg(foreground) + \
|
print(bg(background) + fg(foreground) + \
|
||||||
'{:9.9} {:<1} {:>7.7} {:<1} {:<10.10} {:<1} {:<16.16} {:<1} {:<2.2} {:<1} {:<1.1} {:<1} {:<30.30} {:<1} {:<4.4}'.format(*row) + attr("reset"))
|
'{:9.9} {:<1} {:>7.7} {:<1} {:<10.10} {:<1} '\
|
||||||
|
'{:<16.16} {:<1} {:<2.2} {:<1} {:<1.1} {:<1} {:<30.30} '\
|
||||||
|
'{:<1} {:<4.4}'.format(*row) + attr("reset"))
|
||||||
b_cmd = str.encode("sh/dx/50 @\n")
|
b_cmd = str.encode("sh/dx/50 @\n")
|
||||||
telnet.write(b_cmd)
|
telnet.write(b_cmd)
|
||||||
|
# This is true for every line representing a spot
|
||||||
elif "DX de" in line or "Dx de" in line:
|
elif "DX de" in line or "Dx de" in line:
|
||||||
try:
|
try:
|
||||||
band_col = ""
|
# Extract all necessary fields from the line and store them
|
||||||
|
# into different variables.
|
||||||
call_de = re.search('D(X|x) de (.+?): ', line).group(2)
|
call_de = re.search('D(X|x) de (.+?): ', line).group(2)
|
||||||
freq = re.search(': +(.+?) ', line).group(1)
|
freq = re.search(': +(.+?) ', line).group(1)
|
||||||
call_dx = re.search(freq + ' +(.+?) ', line).group(1)
|
call_dx = re.search(freq + ' +(.+?) ', line).group(1)
|
||||||
time = re.search('[^ ]*$', line).group(0)[0:4]
|
time = re.search('[^ ]*$', line).group(0)[0:4]
|
||||||
comment = re.search(call_dx + ' +(.+?) +' + time, line).group(1)
|
comment = re.search(call_dx + ' +(.+?) +' + time, line).group(1)
|
||||||
|
|
||||||
|
# If the CTY file is available, further information will be
|
||||||
|
# gathered from it, e.g. continent, country, dxcc ID
|
||||||
if self.check_cty:
|
if self.check_cty:
|
||||||
cty_details = self.get_cty_row(call_dx)
|
cty_details = self.get_cty_row(call_dx)
|
||||||
else:
|
else:
|
||||||
|
@ -253,11 +301,16 @@ class ColorSpot():
|
||||||
areaname = cty_details[1]
|
areaname = cty_details[1]
|
||||||
continent = cty_details[3]
|
continent = cty_details[3]
|
||||||
|
|
||||||
|
# If the LotW user activity file is available and the call
|
||||||
|
# sign in question is actually a LotW user, a checkmark is
|
||||||
|
# displayed in a dedicated column of the output
|
||||||
if self.check_lotw_activity and self.check_lotw(call_dx):
|
if self.check_lotw_activity and self.check_lotw(call_dx):
|
||||||
lotw = "✓"
|
lotw = "✓"
|
||||||
else:
|
else:
|
||||||
lotw = ""
|
lotw = ""
|
||||||
|
|
||||||
|
# Depending on the user's choice, the row will be color coded
|
||||||
|
# depending on the band or the DX station's continent
|
||||||
try:
|
try:
|
||||||
if self.config['colors']['color_by'] == "band":
|
if self.config['colors']['color_by'] == "band":
|
||||||
foreground = self.config['band_colors'][freq[:-5]]
|
foreground = self.config['band_colors'][freq[:-5]]
|
||||||
|
@ -268,29 +321,34 @@ class ColorSpot():
|
||||||
except Exception:
|
except Exception:
|
||||||
foreground = "white"
|
foreground = "white"
|
||||||
|
|
||||||
|
# Removes the trailing .0 from a frequency for better readability
|
||||||
freq = freq.replace('.0', '')
|
freq = freq.replace('.0', '')
|
||||||
|
|
||||||
if self.check_lotw_confirmed and cty_details[2] not in self.confirmed_entities:
|
# If the DX station's entity hasn't been worked/confirmed via
|
||||||
|
# LotW yet, the row's background will be color coded.
|
||||||
|
if self.check_lotw_confirmed and \
|
||||||
|
cty_details[2] not in self.confirmed_entities:
|
||||||
background = self.config['colors']['alert_bg']
|
background = self.config['colors']['alert_bg']
|
||||||
foreground = self.config['colors']['alert_fg']
|
foreground = self.config['colors']['alert_fg']
|
||||||
else:
|
else:
|
||||||
background = self.config['colors']['default_bg']
|
background = self.config['colors']['default_bg']
|
||||||
|
|
||||||
|
# color of the table separator
|
||||||
sep = fg("grey_27")+'|'+fg(foreground)
|
sep = fg("grey_27")+'|'+fg(foreground)
|
||||||
|
|
||||||
|
# Contructs the row that will be printed
|
||||||
row = [call_de, sep, freq, sep, call_dx, \
|
row = [call_de, sep, freq, sep, call_dx, \
|
||||||
sep, areaname, sep, continent, sep, lotw, sep, comment, sep, time]
|
sep, areaname, sep, continent, sep, lotw, sep, comment, sep, time]
|
||||||
|
|
||||||
print(bg(background) + fg(foreground) + \
|
print(bg(background) + fg(foreground) + \
|
||||||
'{:9.9} {:<1} {:>7.7} {:<1} {:<10.10} {:<1} {:<16.16} {:<1} {:<2.2} {:<1} {:<1.1} {:<1} {:<30.30} {:<1} {:<4.4}'.format(*row) + attr("reset"))
|
'{:9.9} {:<1} {:>7.7} {:<1} {:<10.10} {:<1} '\
|
||||||
|
'{:<16.16} {:<1} {:<2.2} {:<1} {:<1.1} {:<1} {:<30.30} '\
|
||||||
|
'{:<1} {:<4.4}'.format(*row) + attr("reset"))
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
print(line)
|
print(line)
|
||||||
|
|
||||||
#####################################################
|
|
||||||
# Main Routine #
|
|
||||||
#####################################################
|
|
||||||
def main():
|
def main():
|
||||||
|
"""main routine"""
|
||||||
try:
|
try:
|
||||||
color_spot = ColorSpot()
|
color_spot = ColorSpot()
|
||||||
color_spot.get_spots()
|
color_spot.get_spots()
|
||||||
|
@ -302,6 +360,3 @@ if __name__ == "__main__":
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
except EOFError:
|
except EOFError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 194 KiB |
Loading…
Reference in New Issue