Modifying the source code
Spothole is Public Domain licenced, so you can grab the source code and start modifying it for your own needs. Contributions of code back to the main repository are encouraged, but completely optional.
The source code can be found at https://git.ianrenton.com/ian/spothole.
Sorry this isn't on GitHub. There's too much noise on there now it's been given over to Copilot agents. If you want to contribute code changes, that unfortunately means you'll have to sign up for an account on the developer's Forgejo server (linked above), or email patch files to Ian, M0TRT the old-fashioned way. The hope was that Forgejo federation would be working soon, so that at least you could use a Codeberg account rather than a new login specifically for that instance, but unfortunately we're still waiting on that one!
Code structure
To navigate your way around the source code, this list may help.
Python back-end code
/core- Core classes and utilities/data- Data storage classes/providers/spot- Classes providing spots by accessing the APIs of other services/providers/alert- Classes providing alerts by accessing the APIs of other services/providers/upstream- Classes sending spots and alerts that users add to Spothole on to the APIs of other services/providers/solarconditions- Classes providing solar and propagation by accessing the APIs of other services/providers/staticdata- Classes providing static lookup data by accessing bundled data files or the APIs of other services/providers/callsign- Classes providing callsign lookup data by accessing bundled data files or the APIs of other services/providers/activityrefdata- Classes providing activity reference lookup data by accessing bundled data files or the APIs of other services/webserver- Classes for running Spothole's own web serverspothole.py- Main application script
Templates
/templates- Templates used for constructing Spothole's user-targeted HTML pages
HTML/JS/CSS front-end code
/static- Root for static files served by the web server. These are all served from a path starting/static/./static/apidocs- Contains the OpenAPI spec (openapi.yml)/static/audio- Audio files used by the web front-end/static/css- CSS files used by the web front-end/static/img- image files used by the web front-end/static/js- JavaScript used by the web front-end/static/vendor- Third-party libraries (CSS, JS, fonts and images)
Miscellaneous
/- piprequirements.txt, config, README, etc./misc- Files not directly used by Spothole itself. This includes the screenshots used in the README, example DXSpider custom commands referenced in the documentation, etc./datafiles- Local data files, used by some providers when the data will never change and/or is not easily available online in a format Spothole can handle/cache- Directory where Spothole stores all the data it uses that should be persisted to disk. Created on first run.
Extending the server
Spothole is designed to be easily extensible. If you want to write your own spot provider, for example, simply add a
module to the providers.spot package containing your class. (Currently, in order to be loaded
correctly, the module
(file) name should be the same as the class name, but lower case.)
Your class should extend "SpotProvider"; if it operates by polling an HTTP Server on a timer, it can instead extend " HTTPSpotProvider" where some of the work is done for you.
The class will need to implement a constructor that takes in the provider_config and provides it to the
superclass
constructor, while also taking any other config parameters it needs.
If you're extending the base SpotProvider class, you will need to implement start() and
stop() methods that start
and stop a separate thread which handles the provider's processing needs. The thread should call
submit() or
submit_batch() when it has one or more spots to report.
If you're extending the HTTPSpotProvider class, you will need to provide a URI to query and an interval
to the
superclass constructor. You'll then need to implement the http_response_to_spots() method which is
called when new
data is retrieved. Your implementation should then call submit() or submit_batch() when it
has one or more spots to
report.
When constructing spots, use the comments in the Spot class and the existing implementations as an example. All
parameters are optional, but you will at least want to provide a time (which must be timezone-aware)
and a dx_call.
Finally, simply add the appropriate config to the spot_providers section of config.yml, and
your provider should be
instantiated on startup.
The same approach as above is also used for alerts, and other types of providers. Give Spothole's developers a shout if you need any advice.
If you want users to be able to send spots or alerts on to another service, write an upstream provider in the
providers.upstream package, extending UpstreamProvider, and add it to the
upstream_providers section of config.yml. Implement can_send_spot() and
validate_spot() to provide validation of whether the spot can be sent via the new provider. Implement
send_spot() to do the submission, raising SpotSubmissionError with a helpful message if
the service doesn't accept the spot. Alerts work the same way with the _alert equivalents. Upstream
providers are separate from spot and alert providers, but if they share a name (e.g. "POTA"), Spothole will ask the
spot or alert provider to check for new data straight after something is submitted, so it shows up quickly.
Contributing to Spothole
Contributions from the community are very much welcome. Please bear in mind the following types of contributions you may wish to make, and the associated comments:
- Bug fixes: Very welcome, of course.
- Fixes for bugs found using AI: Accepted with caution. Before submitting, please ensure you understand the change you are recommending, and why it is an improvement.
- User quality of life improvements: Welcome.
- Documentation and infrastructure improvements: Welcome.
- Support for new activities: Welcome.
- API breaking changes: Welcome if they are justifiable improvements. Please note that breaking changes will trigger a new major release and a request to all client developers to update their code, so this should be done with caution.
- New "on theme" features: Welcome. Spothole aims to be an API and web UI that provides spots and alerts from multiple sources, and augments them with as much data as is reasonable. Additional "on theme" features include allowing users to submit spots and alerts, displaying solar/propagation conditions, and activity references. "On theme" feature submissions are in one of these areas.
- New "off theme" features: Discuss with the developers first. In particular, Spothole does not want to replicate what HamAlert or DXSpider already do, and does not intend to offer user accounts or store user data server-side.
- New features written by AI: No thanks. I want to keep Spothole's codebase understood by its developers. If you have a great idea but can't code it yourself, just talk to me about it. I'd rather write it myself slowly than take on a pile of tech debt to implement it immediately.
- Pull requests written by AI: Absolutely not. Please talk to me about your change, one human to another.