Skip to content

Commit 0fe6143

Browse files
committed
Clark - BTC/USDT
0 parents  commit 0fe6143

195 files changed

Lines changed: 34938 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/cd.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: CD para EC2
2+
3+
on:
4+
workflow_run:
5+
workflows: ["CI - Testes e Qualidade"]
6+
types:
7+
- completed
8+
9+
jobs:
10+
deploy:
11+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
12+
runs-on: ubuntu-latest
13+
permissions:
14+
contents: read
15+
packages: write # <-- ESSENCIAL para push no GHCR
16+
17+
steps:
18+
- name: Checkout do código
19+
uses: actions/checkout@v4
20+
21+
- name: Login No GHCR
22+
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
23+
24+
- name: Build Da Imagem
25+
run: |
26+
docker build -t ghcr.io/leayxz/clark:latest .
27+
28+
- name: Push Da Imagem
29+
run: |
30+
docker push ghcr.io/leayxz/clark:latest
31+
32+
- name: Deploy Via SSH
33+
uses: appleboy/[email protected]
34+
with:
35+
host: ${{ secrets.EC2_HOST }}
36+
username: ${{ secrets.EC2_USER }}
37+
key: ${{ secrets.EC2_KEY }}
38+
script: |
39+
cd /home/ubuntu/clark
40+
docker pull ghcr.io/leayxz/clark:latest
41+
docker compose down
42+
docker compose up -d --force-recreate

.github/workflows/ci.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: CI - Testes e Qualidade
2+
3+
on:
4+
push:
5+
branches: [ "*" ] # roda para qualquer push
6+
pull_request:
7+
branches: [ "main" ] # roda em PRs para main
8+
9+
jobs:
10+
ci:
11+
runs-on: ubuntu-latest
12+
env:
13+
DJANGO_SECRET_KEY: "DJANGO_SECRET_KEY"
14+
DEBUG: "True"
15+
CELERY_BROKER_URL: "CELERY_BROKER_URL"
16+
CELERY_RESULT_BACKEND: "CELERY_RESULT_BACKEND"
17+
REDIS_URL: "REDIS_URL"
18+
DB_NAME: "DB_NAME"
19+
DB_USER: "DB_USER"
20+
DB_PASSWORD: "DB_PASSWORD"
21+
DB_HOST: "DB_HOST"
22+
DB_PORT: "DB_PORT"
23+
24+
steps:
25+
- name: Checkout Código
26+
uses: actions/checkout@v3
27+
28+
- name: Configurar Python
29+
uses: actions/setup-python@v4
30+
with:
31+
python-version: "3.13"
32+
33+
- name: Instalar Deps
34+
run: |
35+
python -m pip install --upgrade pip
36+
pip install -r deps.txt
37+
38+
- name: Rodar testes
39+
run: |
40+
pytest

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.env
2+
.env.docker
3+
venv
4+
**/__pycache__/
5+
*.sqlite3

README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
## ⚡ Clark – Automação de Futuros BTC/USDT
2+
- Meu sistema mais completo e modular até o momento, feito para operar contratos futuros de BTC/USDT automaticamente, suportando usuários de forma assíncrona e paralela.
3+
- Com comunicação em tempo real consumindo Websocket e APIs externas, o sistema gerencia tarefas de forma contínua, gerando e validando pagamentos, com uma interface web simples e intuitiva.
4+
5+
### 🚀 TECNOLOGIAS UTILIZADAS
6+
- **Python + Django** – Backend estruturado nas camadas domínio, aplicação, infra e web;
7+
- **HTML/CSS** - Interfaces e formulários simples;
8+
- **PostgreSQL** – Modelado para persistência de pagamentos válidos;
9+
- **Redis** – Cacheando dados de uso frequente e broker para o Celery;
10+
- **Celery** – Tarefas assíncronas contínuas e escaláveis;
11+
- **WebSockets** – Em thread dedicada para atualização de preço em tempo real;
12+
- **Nginx + Gunicorn** – Deploy seguro e performático;
13+
- **Docker + GHCR** – Build e distribuição de imagens para EC2;
14+
- **CI/CD** - Pipelines CI/CD com testes e deploy automático via GitHub Actions;
15+
- **AWS EC2** – Servior de produção para execução contínua;
16+
17+
### 🧠 APRENDIZADOS
18+
- Desenvolvi meu melhor algoritmo até o momento, abrindo compras sem repetir faixas de preço;
19+
- Arquitetura hexagonal, DDD e princípios SOLID, modelando aplicação, domínio, infra e web;
20+
- Criação de pipelines completos de CI/CD;
21+
- Gerenciamento de estado distribuído entre API, tarefas assíncronas e webSocket;
22+
- Configuração de websocket com reconexão;
23+
- Boas práticas de código limpo, organização modular e testes automatizados;
24+
- Integração segura com APIs REST usando autenticação por assinatura HMAC-SHA256;
25+
- Escalabilidade com Celery + Redis;
26+
- Deploy contínuo em Docker, incluindo Gunicorn e Nginx;
27+
- Testes unitários com mocking de integrações externas;
28+
29+
### 📌 FUNCIONALIDADES
30+
- Cadastro e login de usuários;
31+
- Validação de pagamentos e geração de invoices com QRCode;
32+
- Configurações de automação por usuário;
33+
- Trading automático para compras e vendas distribuídas em faixas de preço;
34+
- Notificação automática utilizando API externa;
35+
36+
### 📚 CONCLUSÃO E CRÉDITOS
37+
- Desenvolvido por **Leandro R. Martins**
38+
39+
### 📸 IMAGENS DA EXECUÇÃO
40+
![1](imagens/1.png)
41+
![2](imagens/2.png)
42+
![3](imagens/3.png)
43+
![4](imagens/4.png)

_projeto/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from __future__ import absolute_import, unicode_literals
2+
from .celery import app as celery_app
3+
4+
__all__ = ('celery_app',)
5+
6+
# AUTOMATICAMENTE CARREGA O celery.py QUANDO O DJANGO IMPORTAR O _projeto
7+
# SEM ISSO O DJANGO NAO IMPORTA AUTOMATICAMENTE AS CONFIGURACOES DO celery.py

_projeto/asgi.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import os
2+
3+
from django.core.asgi import get_asgi_application
4+
5+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '_projeto.settings')
6+
7+
application = get_asgi_application()

_projeto/celery.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import os
2+
from celery import Celery
3+
4+
# SETTINGS PADRAO DJANGO
5+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '_projeto.settings')
6+
7+
app = Celery('_projeto')
8+
9+
# LE CONFIGURACAO DJANGO COM "CELERY_"
10+
app.config_from_object('django.conf:settings', namespace = 'CELERY')
11+
12+
# AUTO-DISCOVER TASKS.PY
13+
app.autodiscover_tasks()
14+
15+
# ARQUIVO DE CONFIGURACAO DO CELERY

_projeto/settings.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import os
2+
from pathlib import Path
3+
from decouple import config
4+
5+
BASE_DIR = Path(__file__).resolve().parent.parent
6+
7+
SECRET_KEY = config('DJANGO_SECRET_KEY')
8+
DEBUG = config('DEBUG', cast=bool)
9+
10+
CELERY_BROKER_URL = config('CELERY_BROKER_URL')
11+
CELERY_RESULT_BACKEND = config('CELERY_RESULT_BACKEND')
12+
13+
DATABASES = { 'default': { 'ENGINE':'django.db.backends.postgresql', 'NAME': config('DB_NAME'), 'USER': config('DB_USER'), 'PASSWORD': config('DB_PASSWORD'), 'HOST': config('DB_HOST'), 'PORT': config('DB_PORT')} }
14+
CACHES = {'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': config('REDIS_URL'), 'OPTIONS': {'CLIENT_CLASS': 'django_redis.client.DefaultClient'} }}
15+
16+
STATIC_URL = 'static/'
17+
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
18+
19+
ALLOWED_HOSTS = ['localhost', 'clark.lat', 'www.clark.lat']
20+
CSRF_TRUSTED_ORIGINS = ['https://localhost', 'https://www.clark.lat', 'https://clark.lat']
21+
CSRF_COOKIE_SECURE = True
22+
SESSION_COOKIE_SECURE = True
23+
24+
######################################### ######################################### #########################################
25+
26+
INSTALLED_APPS = [
27+
'django.contrib.admin',
28+
'django.contrib.auth',
29+
'django.contrib.contenttypes',
30+
'django.contrib.sessions',
31+
'django.contrib.messages',
32+
'django.contrib.staticfiles',
33+
34+
'aplicacao',
35+
'dominio',
36+
'infra',
37+
'web',
38+
]
39+
40+
MIDDLEWARE = [
41+
'django.middleware.security.SecurityMiddleware',
42+
'django.contrib.sessions.middleware.SessionMiddleware',
43+
'django.middleware.common.CommonMiddleware',
44+
'django.middleware.csrf.CsrfViewMiddleware',
45+
'django.contrib.auth.middleware.AuthenticationMiddleware',
46+
'django.contrib.messages.middleware.MessageMiddleware',
47+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
48+
]
49+
50+
TEMPLATES = [{
51+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
52+
'DIRS': [],
53+
'APP_DIRS': True,
54+
'OPTIONS': {
55+
'context_processors': [
56+
'django.template.context_processors.request',
57+
'django.contrib.auth.context_processors.auth',
58+
'django.contrib.messages.context_processors.messages', ]}
59+
}]
60+
61+
AUTH_PASSWORD_VALIDATORS = [
62+
{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
63+
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'},
64+
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
65+
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
66+
]
67+
68+
ROOT_URLCONF = '_projeto.urls'
69+
WSGI_APPLICATION = '_projeto.wsgi.application'
70+
71+
LANGUAGE_CODE = 'en-us'
72+
TIME_ZONE = 'America/Sao_Paulo'
73+
USE_I18N = True
74+
USE_TZ = True
75+
76+
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
77+
78+
CELERY_ACCEPT_CONTENT = ['json']
79+
CELERY_TASK_SERIALIZER = 'json'
80+
CELERY_RESULT_SERIALIZER = 'json'
81+
CELERY_TIMEZONE = 'America/Sao_Paulo'

_projeto/urls.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django.contrib import admin
2+
from django.urls import path, include
3+
4+
urlpatterns = [
5+
path('admin/', admin.site.urls),
6+
path('', include("web.urls")),
7+
]

_projeto/wsgi.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import os
2+
from django.core.wsgi import get_wsgi_application
3+
4+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '_projeto.settings')
5+
application = get_wsgi_application()

0 commit comments

Comments
 (0)