Added minimal first version (#1)
Reviewed-on: https://git.cuzo.dev/Parra/crypto-reporter/pulls/1
This commit is contained in:
parent
821f55d31a
commit
0224e02f6a
7 changed files with 480 additions and 0 deletions
152
.drone.yml
Normal file
152
.drone.yml
Normal file
|
@ -0,0 +1,152 @@
|
|||
kind: pipeline
|
||||
type: docker
|
||||
name: arm32
|
||||
|
||||
platform:
|
||||
arch: arm
|
||||
|
||||
steps:
|
||||
- name: Build arm/v7
|
||||
image: registry.cuzo.dev/plugins/docker
|
||||
privileged: true
|
||||
settings:
|
||||
repo: parrazam/crypto-reporter
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-arm
|
||||
mirror: https://registry.cuzo.dev
|
||||
username:
|
||||
from_secret: DOCKER_REGISTRY_USER
|
||||
password:
|
||||
from_secret: DOCKER_REGISTRY_PASSWORD
|
||||
|
||||
image_pull_secrets:
|
||||
- PRIVATE_DOCKER_REGISTRY
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: amd64
|
||||
|
||||
platform:
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
- name: Build amd64
|
||||
image: registry.cuzo.dev/plugins/docker
|
||||
privileged: true
|
||||
volumes:
|
||||
- name: manifest
|
||||
path: docker
|
||||
settings:
|
||||
repo: parrazam/crypto-reporter
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-amd64
|
||||
mirror: https://registry.cuzo.dev
|
||||
username:
|
||||
from_secret: DOCKER_REGISTRY_USER
|
||||
password:
|
||||
from_secret: DOCKER_REGISTRY_PASSWORD
|
||||
|
||||
image_pull_secrets:
|
||||
- PRIVATE_DOCKER_REGISTRY
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: manifest
|
||||
|
||||
steps:
|
||||
- name: Upload manifest
|
||||
image: registry.cuzo.dev/plugins/manifest
|
||||
privileged: true
|
||||
volumes:
|
||||
- name: manifest
|
||||
path: docker
|
||||
settings:
|
||||
target: parrazam/crypto-reporter
|
||||
template: parrazam/crypto-reporter:OS-ARCH
|
||||
auto_tag: true
|
||||
ignore_missing: true
|
||||
username:
|
||||
from_secret: DOCKER_REGISTRY_USER
|
||||
password:
|
||||
from_secret: DOCKER_REGISTRY_PASSWORD
|
||||
platforms:
|
||||
- linux/amd64
|
||||
- linux/arm
|
||||
|
||||
depends_on:
|
||||
- amd64
|
||||
- arm32
|
||||
|
||||
image_pull_secrets:
|
||||
- PRIVATE_DOCKER_REGISTRY
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: release
|
||||
steps:
|
||||
- name: release
|
||||
image: registry.cuzo.dev/plugins/gitea-release
|
||||
settings:
|
||||
api_key:
|
||||
from_secret: DRONE_API_KEY
|
||||
base_url: https://git.cuzo.dev
|
||||
title:
|
||||
from_secret: DRONE_SEMVER
|
||||
when:
|
||||
ref:
|
||||
- refs/tags/*
|
||||
|
||||
depends_on:
|
||||
- manifest
|
||||
|
||||
image_pull_secrets:
|
||||
- PRIVATE_DOCKER_REGISTRY
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: Notify result
|
||||
|
||||
steps:
|
||||
- name: send telegram notification
|
||||
image: registry.cuzo.dev/appleboy/drone-telegram
|
||||
when:
|
||||
status: [success, failure]
|
||||
settings:
|
||||
to:
|
||||
from_secret: TG_USER
|
||||
token:
|
||||
from_secret: TG_TOKEN
|
||||
|
||||
depends_on:
|
||||
- manifest
|
||||
- release
|
||||
|
||||
image_pull_secrets:
|
||||
- PRIVATE_DOCKER_REGISTRY
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- tag
|
162
.gitignore
vendored
Normal file
162
.gitignore
vendored
Normal file
|
@ -0,0 +1,162 @@
|
|||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
.idea/
|
||||
|
9
Dockerfile
Normal file
9
Dockerfile
Normal file
|
@ -0,0 +1,9 @@
|
|||
FROM python:3-alpine
|
||||
|
||||
# Install dependencies:
|
||||
COPY requirements.txt .
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
# Run the application:
|
||||
COPY main.py .
|
||||
CMD ["python", "main.py"]
|
44
README.md
44
README.md
|
@ -1 +1,45 @@
|
|||
# crypto-reporter
|
||||
|
||||
[![Build Status](https://drone.cuzo.dev/api/badges/Parra/crypto-reporter/status.svg)](https://drone.cuzo.dev/Parra/crypto-reporter)
|
||||
|
||||
Obtiene y publica precios de criptomonedas.
|
||||
|
||||
## Instalación y ejecución desde CLI
|
||||
|
||||
Descargar el repositorio en una nueva carpeta:
|
||||
|
||||
````shell
|
||||
git clone https://git.cuzo.dev/Parra/crypto-reporter.git
|
||||
````
|
||||
|
||||
Copiar el fichero `env_file` a `.env` y abrirlo con un editor de textos y editarlo
|
||||
con la información del servidor MQTT, así como editar los tópicos que se quieran usar
|
||||
y el tiempo de refresco.
|
||||
|
||||
Dar permisos de ejecución al fichero principal con `chmod +x main.py` y ejecutar con `./main.py`.
|
||||
|
||||
## Instalación y ejecución desde Docker
|
||||
|
||||
Crear una carpeta (por ejemplo `crypto-reporter`) y acceder a ella.
|
||||
|
||||
Crear un fichero `.env` con el contenido del fichero `env_file` de este repositorio y
|
||||
editarlo con la información del servidor MQTT.
|
||||
|
||||
Crear un fichero `docker-compose.yml` como el siguiente:
|
||||
````yml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
crypto-reporter:
|
||||
image: parrazam/crypto-reporter
|
||||
container_name: crypto-reporter
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./.env:/.env:ro
|
||||
````
|
||||
|
||||
Ejecutar con el comando `docker compose up -d`.
|
||||
|
||||
## Menciones
|
||||
|
||||
La API se extrae de Coingecko y se puede consultar aquí: https://www.coingecko.com/en/api/documentation
|
21
env_file
Normal file
21
env_file
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Log configuration
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
# Crypto configuration
|
||||
CRYPTOS_TO_PUBLISH=bitcoin,ethereum
|
||||
CURRENCIES=eur,usd
|
||||
|
||||
# Broker configuration
|
||||
MQTT_SERVER=
|
||||
MQTT_PORT=
|
||||
MQTT_USER=
|
||||
MQTT_PASSWORD=
|
||||
MQTT_CLIENT_ID=
|
||||
|
||||
# Topic configuration
|
||||
MQTT_TOPIC_PREFIX=
|
||||
|
||||
MQTT_TOPIC_STATE=${MQTT_TOPIC_PREFIX}/state
|
||||
MQTT_TOPIC_DATA=${MQTT_TOPIC_PREFIX}/data
|
||||
|
||||
MQTT_PUBLISH_DELAY=60
|
89
main.py
Normal file
89
main.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
# !/usr/bin/env python3
|
||||
|
||||
"""Crypto reporter"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import requests
|
||||
import time
|
||||
|
||||
from dotenv import load_dotenv
|
||||
import paho.mqtt.client as mqtt
|
||||
|
||||
|
||||
load_dotenv() # Cargamos las variables de entorno necesarias
|
||||
|
||||
LOG_LEVEL = os.getenv('LOG_LEVEL', logging.INFO)
|
||||
|
||||
logging.basicConfig(level=LOG_LEVEL, format='[%(levelname)s] %(asctime)s - %(message)s')
|
||||
|
||||
BASE_API = 'https://api.coingecko.com/api/v3'
|
||||
|
||||
MQTT_TOPIC_DATA = os.getenv('MQTT_TOPIC_DATA', 'crypto-reporter/data')
|
||||
MQTT_TOPIC_STATE = os.getenv('MQTT_TOPIC_STATE', 'crypto-reporter/state')
|
||||
|
||||
MQTT_PUBLISH_DELAY = int(os.getenv('MQTT_PUBLISH_DELAY', 60))
|
||||
MQTT_CLIENT_ID = os.getenv('MQTT_CLIENT_ID', 'crypto-reporter')
|
||||
|
||||
MQTT_SERVER = os.getenv('MQTT_SERVER', 'localhost')
|
||||
MQTT_PORT = int(os.getenv('MQTT_PORT', '1883'))
|
||||
MQTT_USER = os.getenv('MQTT_USER', '')
|
||||
MQTT_PASSWORD = os.getenv('MQTT_PASSWORD', '')
|
||||
|
||||
CRYPTOS_TO_PUBLISH = os.getenv('CRYPTOS_TO_PUBLISH', 'bitcoin')
|
||||
CURRENCIES = os.getenv('CURRENCIES', 'eur')
|
||||
|
||||
|
||||
def on_connect(client, userdata, flags, rc):
|
||||
logging.info("Connected to MQTT server.")
|
||||
client.publish(MQTT_TOPIC_STATE, 'connected', 1, True)
|
||||
|
||||
|
||||
def main():
|
||||
logging.info(f'Connecting to MQTT host {MQTT_SERVER}:{MQTT_PORT}...')
|
||||
mqttc = mqtt.Client(MQTT_CLIENT_ID)
|
||||
mqttc.username_pw_set(MQTT_USER, MQTT_PASSWORD)
|
||||
mqttc.will_set(MQTT_TOPIC_STATE, 'disconnected', 1, True)
|
||||
mqttc.on_connect = on_connect
|
||||
|
||||
mqttc.connect(MQTT_SERVER, MQTT_PORT, 60)
|
||||
mqttc.loop_start()
|
||||
last_msg_time = time.time()
|
||||
|
||||
while True:
|
||||
try:
|
||||
x = requests.get(BASE_API + '/simple/price',
|
||||
params={'ids': CRYPTOS_TO_PUBLISH,
|
||||
'vs_currencies': CURRENCIES})
|
||||
logging.debug(f'HTTP response: {x.status_code}')
|
||||
publish_data(mqttc, x.text)
|
||||
|
||||
delay_gap = time.time() - last_msg_time
|
||||
if delay_gap < MQTT_PUBLISH_DELAY:
|
||||
time.sleep(MQTT_PUBLISH_DELAY - delay_gap)
|
||||
last_msg_time = time.time()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logging.info("exiting...")
|
||||
exit(0)
|
||||
except Exception:
|
||||
logging.exception("something went wrong.")
|
||||
exit(1)
|
||||
|
||||
|
||||
def publish_data(mqttc, raw):
|
||||
try:
|
||||
logging.debug(f'RAW message to publish: {raw}')
|
||||
data = json.loads(raw)
|
||||
for crypto in data:
|
||||
currencies = data[crypto]
|
||||
for currency in currencies:
|
||||
mqttc.publish(MQTT_TOPIC_DATA + f'/{crypto}/{currency}', data[crypto][currency], 1, True)
|
||||
except AttributeError:
|
||||
logging.exception("Error decoding JSON")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.info('Starting crypto broker')
|
||||
main()
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
paho-mqtt==1.6.1
|
||||
python-dotenv==0.21.0
|
||||
requests==2.28.1
|
Loading…
Reference in a new issue