├── .coveragerc ├── .flake8 ├── .github └── workflows │ └── django_project.yml ├── .gitignore ├── .landscape.yml ├── .pyup.yml ├── LICENSE ├── Pipfile ├── Pipfile.lock ├── Procfile ├── README.md ├── conftest.py ├── contrib └── env-sample ├── docker-compose.yml ├── frontend ├── package.json └── scss │ └── custom.scss ├── manage.py ├── pytest.ini └── pythonpro ├── __init__.py ├── absolute_uri.py ├── celery.py ├── checkout ├── __init__.py ├── apps.py ├── facade.py ├── forms.py ├── migrations │ ├── 0001_payment_setup.py │ ├── 0002_webdev_setup.py │ ├── 0003_data_science_setup.py │ ├── 0004_bootcamp_setup.py │ ├── 0005_python_avancado_setup.py │ ├── 0006_webinar_setup.py │ ├── 0007_webserie_and_webinar_boleto.py │ ├── 0008_thiago_avelino_checkouts.py │ └── __init__.py ├── static │ ├── checkout │ │ ├── css │ │ │ ├── normalize.css │ │ │ ├── python-pro.webflow.css │ │ │ └── webflow.css │ │ ├── images │ │ │ ├── 62-626208_python-logo-png-transparent-background-python-logo-png.jpg │ │ │ ├── CAPA_PythonDjango-FRENTESite.jpg │ │ │ ├── DSC_7555.png │ │ │ ├── ana-paula-batalha-4.jpg │ │ │ ├── card-bx.svg │ │ │ ├── charles-tenorio.jpeg │ │ │ ├── city-bx.svg │ │ │ ├── favicon.png │ │ │ ├── guido-luz.jpeg │ │ │ ├── home-bx.svg │ │ │ ├── mail-bx.svg │ │ │ ├── marcelo-andriolli.jpg │ │ │ ├── maria-elisa.png │ │ │ ├── pablo-gabriel.jpeg │ │ │ ├── phone-bx.svg │ │ │ ├── python-pro-bg.svg │ │ │ ├── rafael-ramos.jpeg │ │ │ ├── regis-santos.jpeg │ │ │ ├── site_preview.png │ │ │ ├── user-bx.svg │ │ │ ├── webclip.png │ │ │ └── white_bg.svg │ │ └── js │ │ │ └── webflow.js │ └── thanks │ │ ├── css │ │ ├── normalize.css │ │ ├── python-pro.webflow.css │ │ └── webflow.css │ │ ├── images │ │ ├── Camada-8-p-500.png │ │ ├── Camada-8.png │ │ ├── NoPath---Copia.png │ │ ├── NoPath.png │ │ ├── down-arrow.svg │ │ ├── error.svg │ │ ├── favicon.png │ │ ├── gift-lace.svg │ │ ├── python-pro-bg.svg │ │ ├── webclip.png │ │ ├── white_bg.svg │ │ ├── white_bg_1.svg │ │ └── x.svg │ │ └── js │ │ └── webflow.js ├── templates │ ├── checkout │ │ ├── _bootcamp_lp_payment_block.html │ │ ├── bootcamp_lp_d1.html │ │ ├── bootcamp_lp_d2.html │ │ ├── bootcamp_lp_d3.html │ │ ├── bootcamp_lp_subscription_closed.html │ │ ├── bootcamp_lp_subscription_open.html │ │ ├── webdev_landing_page.html │ │ ├── webdev_landing_page_50_off.html │ │ └── webdev_landing_page_oto.html │ └── django_pagarme │ │ ├── contact_form.html │ │ ├── contact_form_errors.html │ │ ├── pagarme.html │ │ ├── pagarme_bootcamp.html │ │ ├── pagarme_bootcamp_35_discount.html │ │ ├── pagarme_bootcamp_50_discount.html │ │ ├── pagarme_bootcamp_d1_boleto.html │ │ ├── pagarme_bootcamp_lista_de_espera.html │ │ ├── pagarme_bootcamp_lote0.html │ │ ├── pagarme_bootcamp_lote1_comercial.html │ │ ├── pagarme_bootcamp_lote1_pagina_de_vendas.html │ │ ├── pagarme_bootcamp_lote1_whatsapp.html │ │ ├── pagarme_bootcamp_lote2_comercial.html │ │ ├── pagarme_bootcamp_lote2_pagina_de_vendas.html │ │ ├── pagarme_bootcamp_lote2_whatsapp.html │ │ ├── pagarme_bootcamp_lote3_comercial.html │ │ ├── pagarme_bootcamp_lote3_pagina_de_vendas.html │ │ ├── pagarme_bootcamp_lote3_whatsapp.html │ │ ├── pagarme_bootcamp_webdev.html │ │ ├── pagarme_bootcamp_webdev_35_discount.html │ │ ├── pagarme_bootcamp_webdev_50_discount.html │ │ ├── pagarme_comunidade_devpro.html │ │ ├── pagarme_django_para_profissionais.html │ │ ├── pagarme_djangopro.html │ │ ├── pagarme_djangopro_comercial.html │ │ ├── pagarme_djangopro_promocao_especial.html │ │ ├── pagarme_djangopro_promocao_especial_comercial.html │ │ ├── pagarme_djangopro_promocao_especial_deschamps.html │ │ ├── pagarme_jrpv_lista_vip.html │ │ ├── pagarme_jrpv_lista_vip_promocao.html │ │ ├── pagarme_pacote_proximo_nivel.html │ │ ├── pagarme_programa_de_aceleracao.html │ │ ├── pagarme_programa_de_aceleracao_upgrade.html │ │ ├── pagarme_renovacao_comunidade_devpro.html │ │ ├── pagarme_webdev.html │ │ ├── pagarme_webdev_downsell.html │ │ ├── pagarme_webdev_downsell_boleto.html │ │ ├── pagarme_webdev_oto.html │ │ ├── show_boleto_data.html │ │ ├── thanks.html │ │ ├── thanks_aps.html │ │ ├── thanks_bootcamp.html │ │ ├── thanks_bootcamp_35_discount.html │ │ ├── thanks_bootcamp_50_discount.html │ │ ├── thanks_bootcamp_d1_boleto.html │ │ ├── thanks_bootcamp_webdev_35_discount.html │ │ ├── thanks_bootcamp_webdev_50_discount.html │ │ ├── thanks_jrpv_lista_vip.html │ │ └── unavailable_payment_item.html ├── tests │ ├── __init__.py │ ├── conftest.py │ └── test_payment_setup.py ├── urls.py └── views.py ├── cohorts ├── __init__.py ├── admin.py ├── apps.py ├── facade.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_liveclass.py │ ├── 0003_webinar.py │ ├── 0004_cohortstudent_added.py │ ├── 0005_auto_20180612_1206.py │ ├── 0006_auto_20190226_1830.py │ ├── 0007_auto_20190226_1843.py │ ├── 0008_auto_20190307_1712.py │ ├── 0009_increase_webinar_title_length.py │ ├── 0010_add_memberkit_url_to_cohort_contents.py │ └── __init__.py ├── models.py ├── tests │ ├── __init__.py │ ├── conftest.py │ ├── test_cohorts.py │ └── test_live_class_detail.py ├── urls.py └── views.py ├── core ├── __init__.py ├── admin.py ├── apps.py ├── context_processors.py ├── facade.py ├── forms.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ └── seed_dev_db.py ├── managers.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20180530_1801.py │ ├── 0003_auto_20180530_1826.py │ ├── 0004_auto_20180601_1108.py │ ├── 0005_auto_20180603_2026.py │ ├── 0006_user_source.py │ ├── 0007_auto_20190705_0829.py │ ├── 0008_auto_20190812_1627.py │ ├── 0009_auto_20191031_1324.py │ ├── 0010_normalizing_email.py │ ├── 0011_normalizing_lead_email.py │ ├── 0012_added_checkout_form_categories.py │ ├── 0013_auto_webdev_constraints.py │ ├── 0014_auto_become_data_scientist.py │ ├── 0015_become_bootcamper.py │ ├── 0016_become_pythonista.py │ └── __init__.py ├── models.py ├── roles.py ├── static │ ├── css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.css.map │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-grid.min.css.map │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.css.map │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ ├── bootstrap.min.css.map │ │ ├── client.css │ │ ├── custom.css │ │ ├── custom.css.map │ │ ├── default.css │ │ ├── python-birds │ │ │ ├── custom.css │ │ │ ├── custom.min.css │ │ │ ├── magnific-popup.min.css │ │ │ ├── normalize.min.css │ │ │ ├── owl.carousel.min.css │ │ │ └── owl.theme.default.min.css │ │ └── spp │ │ │ ├── bootstrap.css │ │ │ ├── custom.css │ │ │ ├── custom.min.css │ │ │ ├── magnific-popup.min.css │ │ │ ├── normalize.min.css │ │ │ ├── owl.carousel.min.css │ │ │ └── owl.theme.default.min.css │ ├── favicon │ │ ├── python-birds │ │ │ ├── android-chrome-192x192.png │ │ │ ├── android-chrome-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── browserconfig.xml │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── favicon.ico │ │ │ ├── mstile-144x144.png │ │ │ ├── mstile-150x150.png │ │ │ ├── mstile-310x150.png │ │ │ ├── mstile-310x310.png │ │ │ ├── mstile-70x70.png │ │ │ ├── safari-pinned-tab.svg │ │ │ └── site.webmanifest │ │ └── spp │ │ │ ├── android-chrome-192x192.png │ │ │ ├── android-chrome-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── browserconfig.xml │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── favicon.ico │ │ │ ├── mstile-144x144.png │ │ │ ├── mstile-150x150.png │ │ │ ├── mstile-310x150.png │ │ │ ├── mstile-310x310.png │ │ │ ├── mstile-70x70.png │ │ │ ├── safari-pinned-tab.svg │ │ │ └── site.webmanifest │ ├── fonts │ │ ├── Gilroy-Bold.woff │ │ ├── Gilroy-Heavy.woff │ │ ├── Gilroy-Light.woff │ │ ├── Gilroy-Medium.woff │ │ ├── Gilroy-Regular.woff │ │ ├── eot │ │ │ ├── Intelo-900.eot │ │ │ ├── Titillium-300.eot │ │ │ ├── Titillium-500.eot │ │ │ ├── Titillium-700.eot │ │ │ └── Titillium-900.eot │ │ ├── otf │ │ │ ├── Intelo-900.otf │ │ │ ├── Titillium-300.otf │ │ │ ├── Titillium-500.otf │ │ │ ├── Titillium-700.otf │ │ │ └── Titillium-900.otf │ │ ├── svg │ │ │ ├── Intelo-900.svg │ │ │ ├── Titillium-300.svg │ │ │ ├── Titillium-500.svg │ │ │ ├── Titillium-700.svg │ │ │ └── Titillium-900.svg │ │ ├── ttf │ │ │ ├── Intelo-900.ttf │ │ │ ├── Titillium-300.ttf │ │ │ ├── Titillium-500.ttf │ │ │ ├── Titillium-700.ttf │ │ │ └── Titillium-900.ttf │ │ ├── woff │ │ │ ├── Intelo-900.woff │ │ │ ├── Titillium-300.woff │ │ │ ├── Titillium-500.woff │ │ │ ├── Titillium-700.woff │ │ │ └── Titillium-900.woff │ │ └── woff2 │ │ │ ├── Intelo-900.woff2 │ │ │ ├── Titillium-300.woff2 │ │ │ ├── Titillium-500.woff2 │ │ │ ├── Titillium-700.woff2 │ │ │ └── Titillium-900.woff2 │ ├── img │ │ ├── 3.gif │ │ ├── ajax-loader.gif │ │ ├── banner-pagarme.png │ │ ├── compra-segura-1.png │ │ ├── favicon.ico │ │ ├── favicon.png │ │ ├── garantia.png │ │ ├── instructors │ │ │ ├── renzo-nuccitelli-300.jpeg │ │ │ ├── renzo-nuccitelli-300.webp │ │ │ ├── renzo-nuccitelli.jpeg │ │ │ └── renzo-nuccitelli.webp │ │ ├── launch │ │ │ ├── video1-available.png │ │ │ ├── video1-unavailable.png │ │ │ ├── video2-available.png │ │ │ ├── video2-unavailable.png │ │ │ ├── video3-available.png │ │ │ └── video3-unavailable.png │ │ ├── python-birds │ │ │ ├── backgrounds │ │ │ │ └── bg-header.jpg │ │ │ ├── card-python-de-graca.png │ │ │ ├── companies │ │ │ │ ├── companies-detail.png │ │ │ │ ├── logo-google.jpg │ │ │ │ ├── logo-nasa.jpg │ │ │ │ ├── logo-netflix.jpg │ │ │ │ ├── logo-spotify.jpg │ │ │ │ ├── logo-uber.jpg │ │ │ │ └── logo-yahoo.jpg │ │ │ ├── header │ │ │ │ ├── header-detail-middle.png │ │ │ │ ├── header-detail-top-left.jpg │ │ │ │ ├── header-detail-top-right.jpg │ │ │ │ ├── header-renzo-bottom-mobile.jpg │ │ │ │ └── logo-python.png │ │ │ ├── learning │ │ │ │ ├── learning-1_vgsvdd_c_scale,w_200.jpg │ │ │ │ ├── learning-1_vgsvdd_c_scale,w_450.jpg │ │ │ │ ├── learning-1_vgsvdd_c_scale,w_603.jpg │ │ │ │ ├── learning-2_ihqj3j_c_scale,w_200.jpg │ │ │ │ ├── learning-2_ihqj3j_c_scale,w_349.jpg │ │ │ │ ├── learning-2_ihqj3j_c_scale,w_659.jpg │ │ │ │ ├── learning-detail-bottom.jpg │ │ │ │ ├── learning-detail-right.jpg │ │ │ │ └── learning-detail-top.jpg │ │ │ ├── noticia-15-profissoes.webp │ │ │ ├── noticia-9-motivos-conteudo.webp │ │ │ ├── noticia-9-motivos.webp │ │ │ ├── noticia-sobram-vagas.webp │ │ │ ├── noticia-stack-1.webp │ │ │ ├── noticia-stack-2.webp │ │ │ ├── noticia-stack-3.webp │ │ │ ├── testimonials │ │ │ │ ├── testimonials-detail-top.png │ │ │ │ ├── thumb-1.jpg │ │ │ │ ├── thumb-2.jpg │ │ │ │ ├── thumb-3.jpg │ │ │ │ ├── thumb-4.jpg │ │ │ │ ├── thumb-5.jpg │ │ │ │ ├── thumb-6.jpg │ │ │ │ ├── thumb-7.jpg │ │ │ │ └── thumb-8.jpg │ │ │ └── why │ │ │ │ ├── logo-computerworld.jpg │ │ │ │ ├── logo-valor-economico.jpg │ │ │ │ ├── python-detail-bottom-left.jpg │ │ │ │ ├── python-detail-bottom-right.jpg │ │ │ │ ├── python-detail-middle.jpg │ │ │ │ ├── python-detail-top-left.jpg │ │ │ │ ├── python-detail-top-right.png │ │ │ │ ├── why-detail.jpg │ │ │ │ └── why-paper.jpg │ │ ├── renzo-thumb.jpg │ │ ├── renzo-thumb.png │ │ ├── social-proof │ │ │ ├── alisson-americo-1.png │ │ │ ├── alysson.webp │ │ │ ├── carlos-augusto.png │ │ │ ├── charles-tenorio.png │ │ │ ├── diego.webp │ │ │ ├── fabricio.webp │ │ │ ├── ferrabras.webp │ │ │ ├── guido-percu.png │ │ │ ├── isaac.webp │ │ │ ├── jasiel.png │ │ │ ├── jorge-plautz.png │ │ │ ├── marcelo-andreoli.png │ │ │ ├── marcelo.webp │ │ │ ├── marcus-vinicius.png │ │ │ ├── maria-elisa.png │ │ │ ├── pablo.png │ │ │ ├── paulo.png │ │ │ ├── rafael-ramos.png │ │ │ ├── regis-silva.png │ │ │ ├── ricardo-portela.png │ │ │ ├── ronaldo-oliveira.png │ │ │ ├── tanio.png │ │ │ ├── testando-o-mercado.webp │ │ │ ├── vicente.webp │ │ │ ├── vinicius-assef.png │ │ │ └── vinicius.webp │ │ ├── spp │ │ │ ├── card-python-pro.png │ │ │ ├── cards-classes │ │ │ │ ├── card-1.jpg │ │ │ │ ├── card-2.jpg │ │ │ │ ├── image-material.png │ │ │ │ └── image-telegram.png │ │ │ ├── countdown │ │ │ │ └── countdown-detail.png │ │ │ ├── footer-classes │ │ │ │ ├── renzo-desktop.png │ │ │ │ └── renzo-mobile.jpg │ │ │ ├── footer │ │ │ │ ├── cpnj.jpg │ │ │ │ ├── detail-top-footer.png │ │ │ │ ├── email.jpg │ │ │ │ ├── footer-group-detail.jpg │ │ │ │ ├── phone.jpg │ │ │ │ ├── renzo-nuccitelli-footer-desktop.png │ │ │ │ ├── renzo-nuccitelli-footer-desktop.webp │ │ │ │ ├── renzo-nuccitelli-footer.jpg │ │ │ │ ├── renzo-nuccitelli-footer.webp │ │ │ │ ├── renzo-nuccitelli-v2.png │ │ │ │ └── renzo-nuccitelli-v2.webp │ │ │ ├── garantee-main │ │ │ │ └── garantee-badge.png │ │ │ ├── header │ │ │ │ ├── detail-video-header-main.png │ │ │ │ ├── detail-video-header-main.webp │ │ │ │ ├── renzo-nuccitelli-desktop.jpg │ │ │ │ ├── renzo-nuccitelli-desktop.webp │ │ │ │ ├── renzo-nuccitelli-mobile.png │ │ │ │ └── renzo-nuccitelli-mobile.webp │ │ │ ├── interview-main │ │ │ │ └── interview-icon.png │ │ │ ├── pacote-proximo-nivel-mobile.png │ │ │ ├── pacote-proximo-nivel.png │ │ │ ├── people-main │ │ │ │ ├── access-icon.jpg │ │ │ │ ├── adriano-brasileiro.jpg │ │ │ │ ├── certificate-icon.jpg │ │ │ │ ├── eric-gomes.jpg │ │ │ │ ├── isaac-ferreira.jpg │ │ │ │ ├── jessica-ferrari1.jpg │ │ │ │ ├── luiz-vital.jpg │ │ │ │ ├── people-image-detail.png │ │ │ │ ├── rodrigo-vaccari.jpg │ │ │ │ ├── vicente-marcal.jpg │ │ │ │ └── vinicius-assef.jpg │ │ │ ├── renzo-main │ │ │ │ └── renzo-nuccitelli-mobile.png │ │ │ ├── renzo │ │ │ │ ├── about-renzo-nuccitelli-desktop.png │ │ │ │ ├── about-renzo-nuccitelli-desktop.webp │ │ │ │ ├── about-renzo-nuccitelli-mobile.jpg │ │ │ │ └── about-renzo-nuccitelli-mobile.webp │ │ │ ├── summary-main │ │ │ │ ├── bonus-1-desktop.jpg │ │ │ │ ├── bonus-1-mobile.jpg │ │ │ │ ├── bonus-2-desktop.jpg │ │ │ │ ├── bonus-2-mobile.jpg │ │ │ │ ├── bonus-3-desktop.jpg │ │ │ │ ├── bonus-3-mobile.jpg │ │ │ │ ├── summary-card-1.png │ │ │ │ ├── summary-card-2.png │ │ │ │ ├── summary-card-3.png │ │ │ │ ├── summary-card-4.png │ │ │ │ └── summary-price-icon.jpg │ │ │ ├── thank-you │ │ │ │ ├── backgrounds │ │ │ │ │ ├── bg-header-desktop.jpg │ │ │ │ │ └── bg-header-mobile.jpg │ │ │ │ └── steps │ │ │ │ │ ├── step-1-desktop.png │ │ │ │ │ ├── step-1-mobile.jpg │ │ │ │ │ ├── step-2-desktop.png │ │ │ │ │ ├── step-2-mobile.jpg │ │ │ │ │ ├── step-3-desktop.png │ │ │ │ │ ├── step-3-mobile.jpg │ │ │ │ │ ├── step-4-desktop.jpg │ │ │ │ │ └── step-4-mobile.jpg │ │ │ └── thumbs-testimonials │ │ │ │ ├── thumb-1.jpg │ │ │ │ ├── thumb-2.jpg │ │ │ │ ├── thumb-3.jpg │ │ │ │ ├── thumb-4.jpg │ │ │ │ ├── thumb-5.jpg │ │ │ │ ├── thumb-6.jpg │ │ │ │ ├── thumb-7.jpg │ │ │ │ └── thumb-8.jpg │ │ └── whatsapp-loader.gif │ ├── js │ │ ├── bootstrap.bundle.js │ │ ├── bootstrap.bundle.js.map │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.bundle.min.js.map │ │ ├── bootstrap.js │ │ ├── bootstrap.js.map │ │ ├── bootstrap.min.js │ │ ├── bootstrap.min.js.map │ │ ├── jquery-3.2.1.min.js │ │ ├── lazy.js │ │ ├── python-birds │ │ │ ├── jquery.min.js │ │ │ ├── magnific-popup.min.js │ │ │ ├── main.js │ │ │ └── owl.carousel.min.js │ │ ├── sentry.5.3.0.min.js │ │ └── spp │ │ │ ├── OneSignalSDKUpdaterWorker.js │ │ │ ├── OneSignalSDKWorker.js │ │ │ ├── countdown.js │ │ │ ├── countdown.min.js │ │ │ ├── jquery.min.js │ │ │ ├── magnific-popup.min.js │ │ │ └── owl.carousel.min.js │ └── svg │ │ └── spp │ │ ├── blue-arrow-icon.svg │ │ ├── green-arrow-icon.svg │ │ ├── green-camera-icon.svg │ │ ├── instagram-logo.svg │ │ ├── logo-python-pro.svg │ │ ├── logo-semana-do-programador-profissional.svg │ │ ├── twitter-logo.svg │ │ ├── white-camera-icon.svg │ │ ├── x-price-icon.svg │ │ └── youtube-logo.svg ├── templates │ ├── 400.html │ ├── 403.html │ ├── 404.html │ ├── 500.html │ ├── core │ │ ├── _scripts.html │ │ ├── base.html │ │ ├── base_without_nav.html │ │ ├── index.html │ │ ├── instructors.html │ │ ├── lead_change_password.html │ │ ├── lead_form.html │ │ ├── lead_form_errors.html │ │ ├── lead_landing_lite_page.html │ │ ├── lead_landing_page.html │ │ ├── lead_thanks.html │ │ ├── linktree.html │ │ ├── password_email.txt │ │ ├── profile_detail.html │ │ ├── profile_email.html │ │ ├── profile_name.html │ │ ├── profile_password.html │ │ ├── social_proof.html │ │ └── unsubscribe.html │ ├── redirector │ │ └── redirect.html │ ├── registration │ │ ├── login_modal.html │ │ ├── password_reset_complete.html │ │ ├── password_reset_confirm.html │ │ ├── password_reset_done.html │ │ └── password_reset_form.html │ └── two_factor │ │ ├── _base.html │ │ ├── core │ │ ├── backup_tokens.html │ │ ├── login.html │ │ ├── otp_required.html │ │ ├── setup.html │ │ └── setup_complete.html │ │ └── profile │ │ └── profile.html ├── tests │ ├── __init__.py │ ├── test_admin.py │ ├── test_api_register_and_subscribe_fellow.py │ ├── test_email_migration.py │ ├── test_lead_email_migration.py │ ├── test_lead_landing_page.py │ ├── test_linktree.py │ ├── test_login.py │ ├── test_password_reset.py │ ├── test_seed_command.py │ ├── test_sitemaps_and_robots.py │ ├── test_user_creation.py │ ├── test_view_edit_email.py │ ├── test_view_edit_name.py │ ├── test_view_edit_password.py │ ├── test_view_home.py │ ├── test_view_profile.py │ └── test_view_unsubscribe.py ├── urls.py └── views.py ├── dashboard ├── __init__.py ├── admin.py ├── apps.py ├── facade.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20190812_1627.py │ ├── 0003_topic_duration_updated_based_on_interaction.py │ └── __init__.py ├── models.py ├── static │ └── dashboard │ │ └── img │ │ └── assinatura-renzo.jpg ├── templates │ └── dashboard │ │ ├── certificate.html │ │ └── home.html ├── templatetags │ ├── __init__.py │ └── dashboard_tags.py ├── tests │ ├── __init__.py │ └── test_interaction_creation.py ├── urls.py └── views.py ├── discord ├── __init__.py ├── admin.py ├── api_client.py ├── apps.py ├── bot.py ├── facade.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ ├── clean_discord_users.py │ │ └── warn_users_about_subscription_expiration.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_discord_user_created_at_desc_index.py │ ├── 0003_create_discord_lead.py │ └── __init__.py ├── models.py ├── tasks.py ├── templates │ └── discord │ │ └── access_denied.html ├── tests │ ├── __init__.py │ ├── test_api_client.py │ ├── test_clean_discord_user.py │ ├── test_commands.py │ ├── test_discord_integration.py │ └── test_warn_subscription_expiration.py ├── urls.py └── views.py ├── discourse ├── __init__.py ├── apps.py ├── facade.py ├── tests │ ├── __init__.py │ ├── test_sso.py │ └── test_sync.py ├── urls.py └── views.py ├── django_assertions.py ├── domain ├── README.md ├── __init__.py ├── checkout_domain.py ├── content_statistics_domain.py ├── hotzapp_domain.py ├── subscription_domain.py ├── tests │ ├── __init__.py │ ├── test_certificate.py │ ├── test_checkout │ │ ├── __init__.py │ │ ├── conftest.py │ │ ├── test_boleto_generation.py │ │ ├── test_contact_info.py │ │ ├── test_credit_card_payment.py │ │ ├── test_hotzapp.py │ │ ├── test_payment_handler.py │ │ ├── test_payment_page.py │ │ ├── test_thanks.py │ │ └── test_unavailable_product.py │ ├── test_content_completion.py │ ├── test_lead.py │ ├── test_subscriptions_page.py │ └── test_user_services_sinchronization.py └── user_domain.py ├── email_marketing ├── __init__.py ├── apps.py ├── facade.py └── tests │ ├── test_grant_role.py │ └── test_user_creation.py ├── launch ├── __init__.py ├── apps.py ├── facade.py ├── forms.py ├── templates │ └── launch │ │ ├── _navbar.html │ │ ├── _whatsapp_widget.html │ │ ├── cpl.html │ │ ├── form.html │ │ ├── landing_page.html │ │ ├── member_landing_page_subscription_closed.html │ │ ├── member_landing_page_subscription_open.html │ │ ├── membership_email.txt │ │ ├── meteoric_landing_page_open.html │ │ ├── ty.html │ │ └── vip-list.html ├── tests │ ├── __init__.py │ ├── test_cpl.py │ ├── test_cpl1.py │ ├── test_cpl2.py │ ├── test_cpl3.py │ ├── test_cpl4.py │ ├── test_landing_page.py │ ├── test_launch_status.py │ ├── test_lead_form.py │ ├── test_ty.py │ └── test_vip_list.py ├── urls.py └── views.py ├── memberkit ├── __init__.py ├── admin.py ├── api.py ├── apps.py ├── facade.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ ├── create_subscriptions_for_roles.py │ │ ├── fix_inactive_subscriptions.py │ │ ├── inactivate_expired_subscriptions.py │ │ └── synchronize_paid_subscriptions.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_create_relationship_with_payment_config_item.py │ ├── 0003_subscription.py │ ├── 0004_add_membership_activation_data.py │ ├── 0005_create_tags_for_discourse_email_marketing_subscription.py │ ├── 0006_include_cohort_subscription_flag.py │ ├── 0007_allow_subscripiton_be_saved_without_payment.py │ ├── 0008_added_days_of_access_field.py │ ├── 0009_altered_subscription_default_to_one_year.py │ ├── 0010_added_has_discord_access.py │ ├── 0011_alter_subscription_status.py │ ├── 0012_added_subscription_expired_at.py │ ├── 0013_populate_expired_at.py │ ├── 0014_alter_subscription_days_of_access_and_more.py │ └── __init__.py ├── models.py ├── templates │ └── memberkit │ │ ├── manual_migration.html │ │ └── subscriptiontype │ │ └── synchronize_button.html ├── tests │ ├── __init__.py │ ├── test_api.py │ ├── test_commands.py │ ├── test_process_expired_subscriptions.py │ ├── test_subscription_summary.py │ ├── test_subscription_type_synchronization.py │ ├── test_subscriptions_expired_at.py │ ├── test_user_management.py │ └── test_views.py └── views.py ├── modules ├── __init__.py ├── admin.py ├── apps.py ├── chapters_urls.py ├── chapters_views.py ├── context_processors.py ├── facade.py ├── fixtures │ ├── pythonpro_contents.json │ └── pythonpro_modules.json ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20180314_1122.py │ ├── 0003_module.py │ ├── 0004_section_module.py │ ├── 0005_auto_20180314_1817.py │ ├── 0006_chapter.py │ ├── 0007_topic.py │ ├── 0008_topic_discourse_topic_id.py │ ├── 0009_auto_20180319_0020.py │ ├── 0010_auto_20190226_1830.py │ ├── 0011_created_duration_on_topic.py │ ├── 0012_create_memberkit_url.py │ └── __init__.py ├── models.py ├── module_urls.py ├── modules_views.py ├── permissions.py ├── sections_urls.py ├── sections_views.py ├── templates │ ├── chapters │ │ └── chapter_detail.html │ ├── modules │ │ ├── module_description.html │ │ ├── module_detail.html │ │ ├── module_enrol.html │ │ └── module_index.html │ ├── sections │ │ └── section_detail.html │ └── topics │ │ └── topic_detail.html ├── tests │ ├── __init__.py │ ├── test_chapters_view.py │ ├── test_module_description_view.py │ ├── test_module_detail_view.py │ ├── test_module_index_view.py │ ├── test_module_index_view_roles_access.py │ ├── test_next_content.py │ ├── test_previous_content.py │ ├── test_sections_view.py │ └── test_topics_view.py ├── topics_urls.py └── topics_views.py ├── pages ├── __init__.py ├── apps.py ├── forms.py ├── templates │ └── pages │ │ ├── base.html │ │ ├── base_thank_you.html │ │ ├── bootcamp_vip_landing_page.html │ │ ├── bootcamp_vip_thank_you_page.html │ │ ├── carreira_pro_landing_page.html │ │ ├── carreira_pro_thank_you_page.html │ │ ├── ds_webinar_landing_page.html │ │ ├── ds_webinar_thank_you_page.html │ │ ├── leads_onboarding_page.html │ │ ├── pixeling_page.html │ │ ├── tpp_masterclass_landing_page.html │ │ ├── tpp_masterclass_thank_you_page.html │ │ ├── tpp_webiorico_landing_page.html │ │ ├── tpp_webiorico_landing_page_v2.html │ │ └── tpp_webiorico_thank_you_page.html ├── tests │ ├── __init__.py │ ├── test_bootcamp_vip_landing_page.py │ ├── test_carreirapro_landing_page.py │ ├── test_leads_onboarding_page.py │ └── test_view_base.py ├── urls.py └── views.py ├── redirector ├── __init__.py ├── admin.py ├── apps.py ├── facade.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20200421_2144.py │ ├── 0003_redirect_use_javascript.py │ ├── 0004_redirectlink_total_access.py │ └── __init__.py ├── models.py ├── tests │ ├── __init__.py │ ├── test_redirect_by_headers.py │ ├── test_redirect_by_javascript.py │ ├── test_redirect_by_query_string.py │ └── test_redirect_rotating_links.py ├── urls.py └── views.py ├── settings.py ├── tests ├── __init__.py ├── test_urls.py └── test_wsgi.py ├── urls.py └── wsgi.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source=pythonpro 3 | 4 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | exclude=.venv 4 | -------------------------------------------------------------------------------- /.landscape.yml: -------------------------------------------------------------------------------- 1 | python-targets: 2 | - 3 3 | 4 | uses: 5 | - django 6 | 7 | ignore-paths: 8 | - staticfiles 9 | - pythonpro/core/static 10 | - pythonpro/wsgi.py 11 | - pythonpro/core/migrations 12 | - pythonpro/core/admin.py -------------------------------------------------------------------------------- /.pyup.yml: -------------------------------------------------------------------------------- 1 | requirements: 2 | - Pipfile 3 | - Pipfile.lock -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | release: python manage.py sync_roles & python manage.py migrate --noinput 2 | web: gunicorn pythonpro.wsgi --log-file - 3 | worker: celery --app pythonpro.celery worker --loglevel=info 4 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | 3 | services: 4 | database: 5 | container_name: pythonpro_database 6 | image: postgres:15.2 7 | volumes: 8 | - ./.pgdata:/var/lib/postgresql/data 9 | environment: 10 | - LC_ALL=C.UTF-8 11 | - POSTGRES_PASSWORD=postgres 12 | - POSTGRES_USER=postgres 13 | ports: 14 | - 5432:5432 15 | celery_broker: 16 | container_name: pythonpro_celery_broker 17 | image: rabbitmq:3.8.2 18 | ports: 19 | - 5672:5672 20 | redis: 21 | container_name: pythonpro_redis 22 | image: redis:5.0.7 23 | ports: 24 | - 6379:6379 25 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pythonpro-website", 3 | "version": "0.1.0", 4 | "description": "Customizing Twitter Bootstrap 4", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "scss": "node-sass -watch scss -o css" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bootstrap": "^4.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /frontend/scss/custom.scss: -------------------------------------------------------------------------------- 1 | $green: #9fd25f; 2 | $blue: #178eee; 3 | $yellow: #ffcc29; 4 | @import "../node_modules/bootstrap/scss/bootstrap"; 5 | 6 | $theme-colors: ( 7 | "primary": #178eee, 8 | "success": #9fd25f, 9 | "warning": #ffcc29 10 | ); -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pythonpro.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError as exc: 10 | raise ImportError( 11 | "Couldn't import Django. Are you sure it's installed and " 12 | "available on your PYTHONPATH environment variable? Did you " 13 | "forget to activate a virtual environment?" 14 | ) from exc 15 | execute_from_command_line(sys.argv) 16 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | DJANGO_SETTINGS_MODULE=pythonpro.settings 3 | python_files=test*.py *tests.py 4 | junit_family=xunit2 5 | -------------------------------------------------------------------------------- /pythonpro/__init__.py: -------------------------------------------------------------------------------- 1 | from .celery import app as celery_app # noqa 2 | 3 | __all__ = ('celery_app',) 4 | -------------------------------------------------------------------------------- /pythonpro/absolute_uri.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | 4 | def build_absolute_uri(path: str) -> str: 5 | """ 6 | Calculate absolute url by extraction first domain from settings.ALLOWED_HOSTS 7 | :param path: string with path 8 | :return: path concatenated with domain 9 | """ 10 | first_host = settings.ALLOWED_HOSTS[0] 11 | return f'{first_host}{path}' 12 | -------------------------------------------------------------------------------- /pythonpro/celery.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from celery import Celery 4 | from django.conf import settings 5 | 6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pythonpro.settings') 7 | app = Celery('pythonpro.celery') 8 | app.config_from_object(settings, namespace='CELERY') 9 | app.autodiscover_tasks() 10 | -------------------------------------------------------------------------------- /pythonpro/checkout/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/__init__.py -------------------------------------------------------------------------------- /pythonpro/checkout/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CheckoutConfig(AppConfig): 5 | name = 'pythonpro.checkout' 6 | -------------------------------------------------------------------------------- /pythonpro/checkout/facade.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | from django.utils import timezone 4 | 5 | launch_datetime_begin = timezone.make_aware(datetime(2021, 1, 5, 0, 0, 0)) 6 | discount_50_percent_datetime_limit = timezone.make_aware(datetime(2021, 1, 18, 23, 59, 59)) 7 | discount_35_percent_datetime_limit = timezone.make_aware(datetime(2021, 1, 19, 23, 59, 59)) 8 | launch_datetime_finish = timezone.make_aware(datetime(2021, 1, 20, 23, 59, 59)) 9 | 10 | 11 | def is_launch_open(): 12 | return launch_datetime_begin <= timezone.now() <= launch_datetime_finish 13 | 14 | 15 | def has_50_percent_discount(): 16 | return is_launch_open() and (timezone.now() <= discount_50_percent_datetime_limit) 17 | 18 | 19 | def has_35_percent_discount(): 20 | return is_launch_open() and ( 21 | discount_50_percent_datetime_limit < timezone.now() <= discount_35_percent_datetime_limit 22 | ) 23 | -------------------------------------------------------------------------------- /pythonpro/checkout/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | 4 | class WaitingForm(forms.Form): 5 | first_name = forms.CharField( 6 | label="", widget=forms.TextInput(attrs={'placeholder': 'Digite seu nome'}) 7 | ) 8 | email = forms.EmailField( 9 | label="", widget=forms.EmailInput(attrs={'placeholder': 'Digite seu MELHOR email'}) 10 | ) 11 | phone = forms.CharField( 12 | label="", widget=forms.TextInput(attrs={'placeholder': 'Digite seu WhatsApp (não se esqueça do DDD)'}) 13 | ) 14 | -------------------------------------------------------------------------------- /pythonpro/checkout/migrations/0003_data_science_setup.py: -------------------------------------------------------------------------------- 1 | from django.db import migrations 2 | 3 | 4 | def setup_payment_configs(apps, schema_editor): 5 | PagarmeFormConfig = apps.get_model('django_pagarme', 'PagarmeFormConfig') 6 | PagarmeItemConfig = apps.get_model('django_pagarme', 'PagarmeItemConfig') 7 | print() 8 | setup_payment_configs_function(PagarmeFormConfig, PagarmeItemConfig) 9 | 10 | 11 | def setup_payment_configs_function(PagarmeFormConfig, PagarmeItemConfig): 12 | """""" 13 | config = PagarmeFormConfig.objects.first() 14 | 15 | PagarmeItemConfig( 16 | name='Ciência de Dados', 17 | slug='data-science', 18 | price=49700, 19 | tangible=False, 20 | default_config=config, 21 | ).save() 22 | 23 | 24 | class Migration(migrations.Migration): 25 | dependencies = [ 26 | ('checkout', '0002_webdev_setup'), 27 | ] 28 | 29 | operations = [ 30 | migrations.RunPython(setup_payment_configs, migrations.RunPython.noop) 31 | ] 32 | -------------------------------------------------------------------------------- /pythonpro/checkout/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/migrations/__init__.py -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/62-626208_python-logo-png-transparent-background-python-logo-png.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/62-626208_python-logo-png-transparent-background-python-logo-png.jpg -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/CAPA_PythonDjango-FRENTESite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/CAPA_PythonDjango-FRENTESite.jpg -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/DSC_7555.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/DSC_7555.png -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/ana-paula-batalha-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/ana-paula-batalha-4.jpg -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/card-bx.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/charles-tenorio.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/charles-tenorio.jpeg -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/city-bx.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/favicon.png -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/guido-luz.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/guido-luz.jpeg -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/home-bx.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/mail-bx.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/marcelo-andriolli.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/marcelo-andriolli.jpg -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/maria-elisa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/maria-elisa.png -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/pablo-gabriel.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/pablo-gabriel.jpeg -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/rafael-ramos.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/rafael-ramos.jpeg -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/regis-santos.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/regis-santos.jpeg -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/site_preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/site_preview.png -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/user-bx.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/checkout/static/checkout/images/webclip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/checkout/images/webclip.png -------------------------------------------------------------------------------- /pythonpro/checkout/static/thanks/images/Camada-8-p-500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/thanks/images/Camada-8-p-500.png -------------------------------------------------------------------------------- /pythonpro/checkout/static/thanks/images/Camada-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/thanks/images/Camada-8.png -------------------------------------------------------------------------------- /pythonpro/checkout/static/thanks/images/NoPath---Copia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/thanks/images/NoPath---Copia.png -------------------------------------------------------------------------------- /pythonpro/checkout/static/thanks/images/NoPath.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/thanks/images/NoPath.png -------------------------------------------------------------------------------- /pythonpro/checkout/static/thanks/images/down-arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/checkout/static/thanks/images/error.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/checkout/static/thanks/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/thanks/images/favicon.png -------------------------------------------------------------------------------- /pythonpro/checkout/static/thanks/images/webclip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/static/thanks/images/webclip.png -------------------------------------------------------------------------------- /pythonpro/checkout/static/thanks/images/x.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/checkout/bootcamp_lp_d2.html: -------------------------------------------------------------------------------- 1 | {% extends "checkout/bootcamp_lp_subscription_open.html" %} 2 | {% load static %} 3 | {% load django_pagarme %} 4 | {% load bootstrap4 %} 5 | 6 | {% block vsl %}https://www.youtube.com/embed/41DjlWEbT1M{% endblock vsl %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/contact_form_errors.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/contact_form.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_35_discount.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp.html' %} 2 | {% block sidebar %} 3 | 7 | {{ block.super }} 8 | 9 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_50_discount.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp.html' %} 2 | {% block sidebar %} 3 | 7 | {{ block.super }} 8 | 9 | {% endblock sidebar %} 10 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_d1_boleto.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp.html' %} 2 | {% block sidebar %} 3 | 7 | {{ block.super }} 8 | 9 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_lista_de_espera.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp_lote3_pagina_de_vendas.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_lote0.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp.html' %} 2 | {% block sidebar %} 3 | 7 | 11 | {{ block.super }} 12 | 13 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_lote1_comercial.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp_lote1_pagina_de_vendas.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_lote1_pagina_de_vendas.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp.html' %} 2 | {% block sidebar %} 3 | 7 | {{ block.super }} 8 | 9 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_lote1_whatsapp.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp_lote1_pagina_de_vendas.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_lote2_comercial.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp_lote2_pagina_de_vendas.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_lote2_pagina_de_vendas.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp.html' %} 2 | {% block sidebar %} 3 | 7 | {{ block.super }} 8 | 9 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_lote2_whatsapp.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp_lote2_pagina_de_vendas.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_lote3_comercial.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp_lote3_pagina_de_vendas.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_lote3_pagina_de_vendas.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_lote3_whatsapp.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp_lote3_pagina_de_vendas.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_webdev.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp.html' %} 2 | {% block sidebar %} 3 | 7 | {{ block.super }} 8 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_webdev_35_discount.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp_35_discount.html' %} 2 | {% block sidebar %} 3 | 7 | {{ block.super }} 8 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_bootcamp_webdev_50_discount.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_bootcamp_50_discount.html' %} 2 | {% block sidebar %} 3 | 7 | {{ block.super }} 8 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_djangopro.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme.html' %} 2 | {% block sidebar %} 3 | 7 | 10 | 14 | 20 | 23 | 26 | 27 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_djangopro_comercial.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_djangopro.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_djangopro_promocao_especial.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_djangopro.html' %} 2 | {% block sidebar %} 3 | 7 | {{ block.super }} 8 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_djangopro_promocao_especial_comercial.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_djangopro_promocao_especial.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_djangopro_promocao_especial_deschamps.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_djangopro_promocao_especial.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_jrpv_lista_vip.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme.html' %} 2 | {% block sidebar %} 3 | 7 | 11 | 15 | 19 | 20 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_jrpv_lista_vip_promocao.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_jrpv_lista_vip.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_pacote_proximo_nivel.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme.html' %} 2 | {% block sidebar %} 3 | 7 | 11 | 14 | 17 | 20 | {% endblock sidebar %} -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_programa_de_aceleracao_upgrade.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_programa_de_aceleracao.html' %} 2 | {% block bonus_block %}1 ano de acesso à Comunidade DevPro{% endblock bonus_block %} 3 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_renovacao_comunidade_devpro.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_comunidade_devpro.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_webdev_downsell.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_webdev.html' %} 2 | 3 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/pagarme_webdev_downsell_boleto.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/pagarme_webdev.html' %} 2 | 3 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/thanks_aps.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Redirecionando APS 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/thanks_bootcamp.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/thanks.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/thanks_bootcamp_35_discount.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/thanks_bootcamp.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/thanks_bootcamp_50_discount.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/thanks_bootcamp.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/thanks_bootcamp_d1_boleto.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/thanks_bootcamp.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/thanks_bootcamp_webdev_35_discount.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/thanks_bootcamp_50_discount.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/thanks_bootcamp_webdev_50_discount.html: -------------------------------------------------------------------------------- 1 | {% extends 'django_pagarme/thanks_bootcamp_50_discount.html' %} 2 | -------------------------------------------------------------------------------- /pythonpro/checkout/templates/django_pagarme/thanks_jrpv_lista_vip.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base_without_nav.html' %} 2 | {% load django_pagarme %} 3 | {% load static %} 4 | {% block title %}Obrigado por se matricular no {{ payment_item_config.name }}{% endblock %} 5 | {% block styles %}{% endblock %} 6 | {% block body_class %}clean-body{% endblock %} 7 | {% block scripts %}{% endblock scripts %} 8 | {% block head %} 9 | 11 | {% endblock head %} 12 | {% block body %} 13 | O conteúdo desta página foi movido permanentemente para o link: 14 | https://www.python.pro.br/r/jrpv-acesso-vip-obrigado 15 | {% endblock body %} 16 | {% block footer %}{% endblock footer %} 17 | -------------------------------------------------------------------------------- /pythonpro/checkout/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/checkout/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/cohorts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/cohorts/__init__.py -------------------------------------------------------------------------------- /pythonpro/cohorts/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CohortsConfig(AppConfig): 5 | name = 'pythonpro.cohorts' 6 | -------------------------------------------------------------------------------- /pythonpro/cohorts/migrations/0002_liveclass.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.6 on 2018-06-04 17:53 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('cohorts', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='LiveClass', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('start', models.DateTimeField()), 19 | ('vimeo_id', models.CharField(blank=True, max_length=11)), 20 | ('cohort', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cohorts.Cohort')), 21 | ], 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pythonpro/cohorts/migrations/0004_cohortstudent_added.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.6 on 2018-06-12 15:05 2 | 3 | import datetime 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('cohorts', '0003_webinar'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='cohortstudent', 16 | name='added', 17 | field=models.DateTimeField(default=datetime.datetime(2018, 6, 12, 0, 0)), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pythonpro/cohorts/migrations/0005_auto_20180612_1206.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.6 on 2018-06-12 15:06 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('cohorts', '0004_cohortstudent_added'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='cohortstudent', 15 | name='added', 16 | field=models.DateTimeField(auto_now_add=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pythonpro/cohorts/migrations/0006_auto_20190226_1830.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-02-26 21:30 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('cohorts', '0005_auto_20180612_1206'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='webinar', 15 | name='description', 16 | field=models.TextField(default='Alterar'), 17 | ), 18 | migrations.AddField( 19 | model_name='webinar', 20 | name='discourse_topic_id', 21 | field=models.CharField(default=726, max_length=11), 22 | ), 23 | migrations.AddField( 24 | model_name='webinar', 25 | name='image', 26 | field=models.ImageField(null=True, upload_to='webinars/'), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /pythonpro/cohorts/migrations/0007_auto_20190226_1843.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-02-26 21:43 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('cohorts', '0006_auto_20190226_1830'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='webinar', 15 | name='description', 16 | field=models.TextField(), 17 | ), 18 | migrations.AlterField( 19 | model_name='webinar', 20 | name='discourse_topic_id', 21 | field=models.CharField(max_length=11), 22 | ), 23 | migrations.AlterField( 24 | model_name='webinar', 25 | name='image', 26 | field=models.ImageField(blank=True, null=True, upload_to='webinars/'), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /pythonpro/cohorts/migrations/0008_auto_20190307_1712.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-07 20:12 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('cohorts', '0007_auto_20190226_1843'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='liveclass', 15 | name='description', 16 | field=models.TextField(blank=True, default='Aula Pendente'), 17 | ), 18 | migrations.AddField( 19 | model_name='liveclass', 20 | name='discourse_topic_id', 21 | field=models.CharField(default='726', max_length=11, null=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pythonpro/cohorts/migrations/0009_increase_webinar_title_length.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2 on 2021-05-20 13:57 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('cohorts', '0008_auto_20190307_1712'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='webinar', 15 | name='slug', 16 | field=models.SlugField(max_length=128, unique=True), 17 | ), 18 | migrations.AlterField( 19 | model_name='webinar', 20 | name='title', 21 | field=models.CharField(max_length=128), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pythonpro/cohorts/migrations/0010_add_memberkit_url_to_cohort_contents.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.4 on 2021-06-03 18:44 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('cohorts', '0009_increase_webinar_title_length'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='liveclass', 15 | name='memberkit_url', 16 | field=models.URLField(blank=True, default='', max_length=1024), 17 | ), 18 | migrations.AddField( 19 | model_name='webinar', 20 | name='memberkit_url', 21 | field=models.URLField(blank=True, default='', max_length=1024), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pythonpro/cohorts/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/cohorts/migrations/__init__.py -------------------------------------------------------------------------------- /pythonpro/cohorts/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/cohorts/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/cohorts/tests/conftest.py: -------------------------------------------------------------------------------- 1 | from os import path 2 | 3 | import pytest 4 | from django.core.files.uploadedfile import SimpleUploadedFile 5 | from model_bakery import baker 6 | 7 | from pythonpro import settings 8 | from pythonpro.cohorts.models import Cohort 9 | 10 | img_path = path.join(settings.BASE_DIR, 'pythonpro', 'core', 'static', 'img', 'instructors', 'renzo-nuccitelli.jpeg') 11 | 12 | 13 | @pytest.fixture 14 | def cohort(client, django_user_model): 15 | user = baker.make(django_user_model) 16 | image = SimpleUploadedFile(name='renzo-nuccitelli.jpeg', content=open(img_path, 'rb').read(), 17 | content_type='image/png') 18 | cohort = baker.make(Cohort, slug='guido-van-rossum', title='Guido van Rossum', students=[user], image=image) 19 | return cohort 20 | -------------------------------------------------------------------------------- /pythonpro/cohorts/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from pythonpro.cohorts import views 4 | 5 | app_name = 'cohorts' 6 | urlpatterns = [ 7 | path('aulas//', views.live_class, name='live_class'), 8 | ] 9 | -------------------------------------------------------------------------------- /pythonpro/cohorts/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.decorators import login_required 2 | from django.shortcuts import redirect 3 | from django.urls import reverse 4 | 5 | from pythonpro.cohorts import facade 6 | from pythonpro.memberkit import facade as memberkit_facade 7 | 8 | 9 | @login_required 10 | def live_class(request, pk): 11 | user = request.user 12 | if memberkit_facade.has_memberkit_account(user): 13 | live_class = facade.find_live_class(pk=pk) 14 | return redirect(live_class.memberkit_url, permanent=True) 15 | if memberkit_facade.has_any_subscription(user): 16 | return redirect(reverse('migrate_to_memberkit'), permanent=True) 17 | return redirect(reverse('checkout:bootcamp_lp'), permanent=False) 18 | -------------------------------------------------------------------------------- /pythonpro/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/__init__.py -------------------------------------------------------------------------------- /pythonpro/core/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CoreConfig(AppConfig): 5 | name = 'pythonpro.core' 6 | -------------------------------------------------------------------------------- /pythonpro/core/context_processors.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | 4 | def global_settings(request): 5 | # return any necessary values 6 | dct = { 7 | 'DEFAULT_FROM_EMAIL': settings.DEFAULT_FROM_EMAIL, 8 | 'DISCOURSE_BASE_URL': settings.DISCOURSE_BASE_URL, 9 | 'GOOGLE_TAG_MANAGER_ID': settings.GOOGLE_TAG_MANAGER_ID, 10 | } 11 | return dct 12 | -------------------------------------------------------------------------------- /pythonpro/core/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/management/__init__.py -------------------------------------------------------------------------------- /pythonpro/core/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/management/commands/__init__.py -------------------------------------------------------------------------------- /pythonpro/core/migrations/0002_auto_20180530_1801.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-05-30 21:01 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('core', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelTable( 14 | name='user', 15 | table=None, 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pythonpro/core/migrations/0004_auto_20180601_1108.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-01 14:08 2 | 3 | from django.db import migrations 4 | import pythonpro.core.managers 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('core', '0003_auto_20180530_1826'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterModelManagers( 15 | name='user', 16 | managers=[ 17 | ('objects', pythonpro.core.managers.UserManager()), 18 | ], 19 | ), 20 | migrations.RemoveField( 21 | model_name='user', 22 | name='last_name', 23 | ), 24 | migrations.RemoveField( 25 | model_name='user', 26 | name='username', 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /pythonpro/core/migrations/0005_auto_20180603_2026.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.6 on 2018-06-03 23:26 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('core', '0004_auto_20180601_1108'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='user', 15 | name='first_name', 16 | field=models.CharField(max_length=30, verbose_name='first name'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pythonpro/core/migrations/0006_user_source.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.2 on 2019-06-24 19:12 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('core', '0005_auto_20180603_2026'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='user', 15 | name='source', 16 | field=models.CharField(blank=True, max_length=255, null=True, verbose_name='source'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pythonpro/core/migrations/0007_auto_20190705_0829.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.2 on 2019-07-05 11:29 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('core', '0006_user_source'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='user', 15 | name='source', 16 | field=models.CharField(default='unknown', max_length=255, verbose_name='source'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pythonpro/core/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/migrations/__init__.py -------------------------------------------------------------------------------- /pythonpro/core/static/css/python-birds/owl.theme.default.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Owl Carousel v2.3.4 3 | * Copyright 2013-2018 David Deutsch 4 | * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE 5 | */ 6 | .owl-theme .owl-dots,.owl-theme .owl-nav{text-align:center;-webkit-tap-highlight-color:transparent}.owl-theme .owl-nav{margin-top:10px}.owl-theme .owl-nav [class*=owl-]{color:#FFF;font-size:14px;margin:5px;padding:4px 7px;background:#D6D6D6;display:inline-block;cursor:pointer;border-radius:3px}.owl-theme .owl-nav [class*=owl-]:hover{background:#869791;color:#FFF;text-decoration:none}.owl-theme .owl-nav .disabled{opacity:.5;cursor:default}.owl-theme .owl-nav.disabled+.owl-dots{margin-top:10px}.owl-theme .owl-dots .owl-dot{display:inline-block;zoom:1}.owl-theme .owl-dots .owl-dot span{width:10px;height:10px;margin:5px 7px;background:#D6D6D6;display:block;-webkit-backface-visibility:visible;transition:opacity .2s ease;border-radius:30px}.owl-theme .owl-dots .owl-dot.active span,.owl-theme .owl-dots .owl-dot:hover span{background:#869791} -------------------------------------------------------------------------------- /pythonpro/core/static/css/spp/owl.theme.default.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Owl Carousel v2.3.4 3 | * Copyright 2013-2018 David Deutsch 4 | * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE 5 | */ 6 | .owl-theme .owl-dots,.owl-theme .owl-nav{text-align:center;-webkit-tap-highlight-color:transparent}.owl-theme .owl-nav{margin-top:10px}.owl-theme .owl-nav [class*=owl-]{color:#FFF;font-size:14px;margin:5px;padding:4px 7px;background:#D6D6D6;display:inline-block;cursor:pointer;border-radius:3px}.owl-theme .owl-nav [class*=owl-]:hover{background:#869791;color:#FFF;text-decoration:none}.owl-theme .owl-nav .disabled{opacity:.5;cursor:default}.owl-theme .owl-nav.disabled+.owl-dots{margin-top:10px}.owl-theme .owl-dots .owl-dot{display:inline-block;zoom:1}.owl-theme .owl-dots .owl-dot span{width:10px;height:10px;margin:5px 7px;background:#D6D6D6;display:block;-webkit-backface-visibility:visible;transition:opacity .2s ease;border-radius:30px}.owl-theme .owl-dots .owl-dot.active span,.owl-theme .owl-dots .owl-dot:hover span{background:#869791} -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/python-birds/android-chrome-192x192.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/python-birds/android-chrome-512x512.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/python-birds/apple-touch-icon.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #ffffff 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/python-birds/favicon-16x16.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/python-birds/favicon-32x32.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/python-birds/favicon.ico -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/python-birds/mstile-144x144.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/python-birds/mstile-150x150.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/python-birds/mstile-310x150.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/python-birds/mstile-310x310.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/python-birds/mstile-70x70.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/python-birds/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Dev Pro", 3 | "short_name": "Dev Pro", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/spp/android-chrome-192x192.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/spp/android-chrome-512x512.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/spp/apple-touch-icon.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #ffffff 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/spp/favicon-16x16.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/spp/favicon-32x32.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/spp/favicon.ico -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/spp/mstile-144x144.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/spp/mstile-150x150.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/spp/mstile-310x150.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/spp/mstile-310x310.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/favicon/spp/mstile-70x70.png -------------------------------------------------------------------------------- /pythonpro/core/static/favicon/spp/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Dev Pro", 3 | "short_name": "Dev Pro", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/Gilroy-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/Gilroy-Bold.woff -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/Gilroy-Heavy.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/Gilroy-Heavy.woff -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/Gilroy-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/Gilroy-Light.woff -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/Gilroy-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/Gilroy-Medium.woff -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/Gilroy-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/Gilroy-Regular.woff -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/eot/Intelo-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/eot/Intelo-900.eot -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/eot/Titillium-300.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/eot/Titillium-300.eot -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/eot/Titillium-500.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/eot/Titillium-500.eot -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/eot/Titillium-700.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/eot/Titillium-700.eot -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/eot/Titillium-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/eot/Titillium-900.eot -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/otf/Intelo-900.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/otf/Intelo-900.otf -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/otf/Titillium-300.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/otf/Titillium-300.otf -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/otf/Titillium-500.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/otf/Titillium-500.otf -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/otf/Titillium-700.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/otf/Titillium-700.otf -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/otf/Titillium-900.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/otf/Titillium-900.otf -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/ttf/Intelo-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/ttf/Intelo-900.ttf -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/ttf/Titillium-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/ttf/Titillium-300.ttf -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/ttf/Titillium-500.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/ttf/Titillium-500.ttf -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/ttf/Titillium-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/ttf/Titillium-700.ttf -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/ttf/Titillium-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/ttf/Titillium-900.ttf -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/woff/Intelo-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/woff/Intelo-900.woff -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/woff/Titillium-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/woff/Titillium-300.woff -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/woff/Titillium-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/woff/Titillium-500.woff -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/woff/Titillium-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/woff/Titillium-700.woff -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/woff/Titillium-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/woff/Titillium-900.woff -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/woff2/Intelo-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/woff2/Intelo-900.woff2 -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/woff2/Titillium-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/woff2/Titillium-300.woff2 -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/woff2/Titillium-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/woff2/Titillium-500.woff2 -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/woff2/Titillium-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/woff2/Titillium-700.woff2 -------------------------------------------------------------------------------- /pythonpro/core/static/fonts/woff2/Titillium-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/fonts/woff2/Titillium-900.woff2 -------------------------------------------------------------------------------- /pythonpro/core/static/img/3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/3.gif -------------------------------------------------------------------------------- /pythonpro/core/static/img/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/ajax-loader.gif -------------------------------------------------------------------------------- /pythonpro/core/static/img/banner-pagarme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/banner-pagarme.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/compra-segura-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/compra-segura-1.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/favicon.ico -------------------------------------------------------------------------------- /pythonpro/core/static/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/favicon.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/garantia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/garantia.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/instructors/renzo-nuccitelli-300.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/instructors/renzo-nuccitelli-300.jpeg -------------------------------------------------------------------------------- /pythonpro/core/static/img/instructors/renzo-nuccitelli-300.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/instructors/renzo-nuccitelli-300.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/instructors/renzo-nuccitelli.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/instructors/renzo-nuccitelli.jpeg -------------------------------------------------------------------------------- /pythonpro/core/static/img/instructors/renzo-nuccitelli.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/instructors/renzo-nuccitelli.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/launch/video1-available.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/launch/video1-available.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/launch/video1-unavailable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/launch/video1-unavailable.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/launch/video2-available.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/launch/video2-available.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/launch/video2-unavailable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/launch/video2-unavailable.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/launch/video3-available.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/launch/video3-available.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/launch/video3-unavailable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/launch/video3-unavailable.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/backgrounds/bg-header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/backgrounds/bg-header.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/card-python-de-graca.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/card-python-de-graca.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/companies/companies-detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/companies/companies-detail.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/companies/logo-google.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/companies/logo-google.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/companies/logo-nasa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/companies/logo-nasa.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/companies/logo-netflix.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/companies/logo-netflix.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/companies/logo-spotify.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/companies/logo-spotify.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/companies/logo-uber.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/companies/logo-uber.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/companies/logo-yahoo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/companies/logo-yahoo.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/header/header-detail-middle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/header/header-detail-middle.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/header/header-detail-top-left.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/header/header-detail-top-left.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/header/header-detail-top-right.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/header/header-detail-top-right.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/header/header-renzo-bottom-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/header/header-renzo-bottom-mobile.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/header/logo-python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/header/logo-python.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/learning/learning-1_vgsvdd_c_scale,w_200.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/learning/learning-1_vgsvdd_c_scale,w_200.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/learning/learning-1_vgsvdd_c_scale,w_450.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/learning/learning-1_vgsvdd_c_scale,w_450.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/learning/learning-1_vgsvdd_c_scale,w_603.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/learning/learning-1_vgsvdd_c_scale,w_603.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/learning/learning-2_ihqj3j_c_scale,w_200.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/learning/learning-2_ihqj3j_c_scale,w_200.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/learning/learning-2_ihqj3j_c_scale,w_349.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/learning/learning-2_ihqj3j_c_scale,w_349.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/learning/learning-2_ihqj3j_c_scale,w_659.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/learning/learning-2_ihqj3j_c_scale,w_659.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/learning/learning-detail-bottom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/learning/learning-detail-bottom.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/learning/learning-detail-right.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/learning/learning-detail-right.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/learning/learning-detail-top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/learning/learning-detail-top.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/noticia-15-profissoes.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/noticia-15-profissoes.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/noticia-9-motivos-conteudo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/noticia-9-motivos-conteudo.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/noticia-9-motivos.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/noticia-9-motivos.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/noticia-sobram-vagas.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/noticia-sobram-vagas.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/noticia-stack-1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/noticia-stack-1.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/noticia-stack-2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/noticia-stack-2.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/noticia-stack-3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/noticia-stack-3.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/testimonials/testimonials-detail-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/testimonials/testimonials-detail-top.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/testimonials/thumb-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/testimonials/thumb-1.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/testimonials/thumb-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/testimonials/thumb-2.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/testimonials/thumb-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/testimonials/thumb-3.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/testimonials/thumb-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/testimonials/thumb-4.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/testimonials/thumb-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/testimonials/thumb-5.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/testimonials/thumb-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/testimonials/thumb-6.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/testimonials/thumb-7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/testimonials/thumb-7.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/testimonials/thumb-8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/testimonials/thumb-8.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/why/logo-computerworld.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/why/logo-computerworld.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/why/logo-valor-economico.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/why/logo-valor-economico.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/why/python-detail-bottom-left.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/why/python-detail-bottom-left.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/why/python-detail-bottom-right.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/why/python-detail-bottom-right.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/why/python-detail-middle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/why/python-detail-middle.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/why/python-detail-top-left.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/why/python-detail-top-left.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/why/python-detail-top-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/why/python-detail-top-right.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/why/why-detail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/why/why-detail.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/python-birds/why/why-paper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/python-birds/why/why-paper.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/renzo-thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/renzo-thumb.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/renzo-thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/renzo-thumb.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/alisson-americo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/alisson-americo-1.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/alysson.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/alysson.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/carlos-augusto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/carlos-augusto.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/charles-tenorio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/charles-tenorio.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/diego.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/diego.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/fabricio.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/fabricio.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/ferrabras.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/ferrabras.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/guido-percu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/guido-percu.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/isaac.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/isaac.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/jasiel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/jasiel.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/jorge-plautz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/jorge-plautz.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/marcelo-andreoli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/marcelo-andreoli.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/marcelo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/marcelo.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/marcus-vinicius.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/marcus-vinicius.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/maria-elisa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/maria-elisa.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/pablo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/pablo.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/paulo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/paulo.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/rafael-ramos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/rafael-ramos.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/regis-silva.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/regis-silva.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/ricardo-portela.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/ricardo-portela.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/ronaldo-oliveira.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/ronaldo-oliveira.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/tanio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/tanio.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/testando-o-mercado.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/testando-o-mercado.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/vicente.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/vicente.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/vinicius-assef.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/vinicius-assef.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/social-proof/vinicius.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/social-proof/vinicius.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/card-python-pro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/card-python-pro.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/cards-classes/card-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/cards-classes/card-1.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/cards-classes/card-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/cards-classes/card-2.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/cards-classes/image-material.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/cards-classes/image-material.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/cards-classes/image-telegram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/cards-classes/image-telegram.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/countdown/countdown-detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/countdown/countdown-detail.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer-classes/renzo-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer-classes/renzo-desktop.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer-classes/renzo-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer-classes/renzo-mobile.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer/cpnj.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer/cpnj.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer/detail-top-footer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer/detail-top-footer.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer/email.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer/email.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer/footer-group-detail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer/footer-group-detail.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer/phone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer/phone.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer/renzo-nuccitelli-footer-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer/renzo-nuccitelli-footer-desktop.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer/renzo-nuccitelli-footer-desktop.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer/renzo-nuccitelli-footer-desktop.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer/renzo-nuccitelli-footer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer/renzo-nuccitelli-footer.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer/renzo-nuccitelli-footer.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer/renzo-nuccitelli-footer.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer/renzo-nuccitelli-v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer/renzo-nuccitelli-v2.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/footer/renzo-nuccitelli-v2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/footer/renzo-nuccitelli-v2.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/garantee-main/garantee-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/garantee-main/garantee-badge.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/header/detail-video-header-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/header/detail-video-header-main.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/header/detail-video-header-main.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/header/detail-video-header-main.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/header/renzo-nuccitelli-desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/header/renzo-nuccitelli-desktop.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/header/renzo-nuccitelli-desktop.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/header/renzo-nuccitelli-desktop.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/header/renzo-nuccitelli-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/header/renzo-nuccitelli-mobile.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/header/renzo-nuccitelli-mobile.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/header/renzo-nuccitelli-mobile.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/interview-main/interview-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/interview-main/interview-icon.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/pacote-proximo-nivel-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/pacote-proximo-nivel-mobile.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/pacote-proximo-nivel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/pacote-proximo-nivel.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/people-main/access-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/people-main/access-icon.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/people-main/adriano-brasileiro.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/people-main/adriano-brasileiro.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/people-main/certificate-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/people-main/certificate-icon.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/people-main/eric-gomes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/people-main/eric-gomes.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/people-main/isaac-ferreira.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/people-main/isaac-ferreira.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/people-main/jessica-ferrari1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/people-main/jessica-ferrari1.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/people-main/luiz-vital.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/people-main/luiz-vital.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/people-main/people-image-detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/people-main/people-image-detail.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/people-main/rodrigo-vaccari.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/people-main/rodrigo-vaccari.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/people-main/vicente-marcal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/people-main/vicente-marcal.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/people-main/vinicius-assef.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/people-main/vinicius-assef.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/renzo-main/renzo-nuccitelli-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/renzo-main/renzo-nuccitelli-mobile.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/renzo/about-renzo-nuccitelli-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/renzo/about-renzo-nuccitelli-desktop.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/renzo/about-renzo-nuccitelli-desktop.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/renzo/about-renzo-nuccitelli-desktop.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/renzo/about-renzo-nuccitelli-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/renzo/about-renzo-nuccitelli-mobile.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/renzo/about-renzo-nuccitelli-mobile.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/renzo/about-renzo-nuccitelli-mobile.webp -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/summary-main/bonus-1-desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/summary-main/bonus-1-desktop.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/summary-main/bonus-1-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/summary-main/bonus-1-mobile.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/summary-main/bonus-2-desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/summary-main/bonus-2-desktop.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/summary-main/bonus-2-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/summary-main/bonus-2-mobile.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/summary-main/bonus-3-desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/summary-main/bonus-3-desktop.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/summary-main/bonus-3-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/summary-main/bonus-3-mobile.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/summary-main/summary-card-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/summary-main/summary-card-1.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/summary-main/summary-card-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/summary-main/summary-card-2.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/summary-main/summary-card-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/summary-main/summary-card-3.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/summary-main/summary-card-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/summary-main/summary-card-4.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/summary-main/summary-price-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/summary-main/summary-price-icon.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thank-you/backgrounds/bg-header-desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thank-you/backgrounds/bg-header-desktop.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thank-you/backgrounds/bg-header-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thank-you/backgrounds/bg-header-mobile.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thank-you/steps/step-1-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thank-you/steps/step-1-desktop.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thank-you/steps/step-1-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thank-you/steps/step-1-mobile.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thank-you/steps/step-2-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thank-you/steps/step-2-desktop.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thank-you/steps/step-2-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thank-you/steps/step-2-mobile.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thank-you/steps/step-3-desktop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thank-you/steps/step-3-desktop.png -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thank-you/steps/step-3-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thank-you/steps/step-3-mobile.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thank-you/steps/step-4-desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thank-you/steps/step-4-desktop.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thank-you/steps/step-4-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thank-you/steps/step-4-mobile.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thumbs-testimonials/thumb-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thumbs-testimonials/thumb-1.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thumbs-testimonials/thumb-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thumbs-testimonials/thumb-2.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thumbs-testimonials/thumb-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thumbs-testimonials/thumb-3.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thumbs-testimonials/thumb-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thumbs-testimonials/thumb-4.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thumbs-testimonials/thumb-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thumbs-testimonials/thumb-5.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thumbs-testimonials/thumb-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thumbs-testimonials/thumb-6.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thumbs-testimonials/thumb-7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thumbs-testimonials/thumb-7.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/spp/thumbs-testimonials/thumb-8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/spp/thumbs-testimonials/thumb-8.jpg -------------------------------------------------------------------------------- /pythonpro/core/static/img/whatsapp-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/static/img/whatsapp-loader.gif -------------------------------------------------------------------------------- /pythonpro/core/static/js/python-birds/main.js: -------------------------------------------------------------------------------- 1 | // SMOOTH SCROLL 2 | $('a[href^="#"]').on('click', function (event) { 3 | var target = $(this.getAttribute('href')); 4 | if (target.length) { 5 | event.preventDefault(); 6 | $('html, body').stop().animate({ 7 | scrollTop: target.offset().top - 100 8 | }, 900); 9 | } 10 | }); 11 | 12 | $(document).ready(function () { 13 | $('.owl-carousel').owlCarousel({ 14 | autoPlay: 3000, 15 | loop: true, 16 | margin: 10, 17 | responsiveClass: true, 18 | dots: true, 19 | responsive: { 20 | 0: { 21 | items: 1, 22 | nav: true 23 | }, 24 | 600: { 25 | items: 3, 26 | nav: false 27 | }, 28 | 1000: { 29 | items: 3, 30 | nav: true, 31 | } 32 | } 33 | }) 34 | }); 35 | 36 | $('.popup-vimeo').magnificPopup({ 37 | src: 'https://vimeo.com/398972182', 38 | type: 'iframe' 39 | }); -------------------------------------------------------------------------------- /pythonpro/core/static/js/spp/OneSignalSDKUpdaterWorker.js: -------------------------------------------------------------------------------- 1 | importScripts('https://cdn.onesignal.com/sdks/OneSignalSDKWorker.js'); 2 | -------------------------------------------------------------------------------- /pythonpro/core/static/js/spp/OneSignalSDKWorker.js: -------------------------------------------------------------------------------- 1 | importScripts('https://cdn.onesignal.com/sdks/OneSignalSDKWorker.js'); 2 | -------------------------------------------------------------------------------- /pythonpro/core/static/js/spp/countdown.js: -------------------------------------------------------------------------------- 1 | function initCountDown(countDown) { 2 | const second = 1000, 3 | minute = second * 60, 4 | hour = minute * 60, 5 | day = hour * 24; 6 | x = setInterval(function () { 7 | let now = new Date().getTime(), 8 | distance = countDown - now; 9 | 10 | let data = { 11 | 'days': distance / (day), 12 | 'hours': (distance % (day)) / (hour), 13 | 'minutes': (distance % (hour)) / (minute), 14 | 'seconds': (distance % (minute)) / second 15 | }; 16 | for (let prop in data) { 17 | for (let element of document.getElementsByClassName(prop)) { 18 | element.innerText = Math.floor(data[prop]); 19 | } 20 | } 21 | 22 | if (distance < 0) { 23 | clearInterval(x); 24 | 'Tempo esgotado!'; 25 | } 26 | }, second) 27 | } -------------------------------------------------------------------------------- /pythonpro/core/static/js/spp/countdown.min.js: -------------------------------------------------------------------------------- 1 | function initCountDown(e) { x = setInterval(function () { let t = (new Date).getTime(), n = e - t, o = { days: n / 864e5, hours: n % 864e5 / 36e5, minutes: n % 36e5 / 6e4, seconds: n % 6e4 / 1e3 }; for (let e in o) for (let t of document.getElementsByClassName(e)) t.innerText = Math.floor(o[e]); n < 0 && clearInterval(x) }, 1e3) } initCountDown(new Date("Aug 10, 2020 23:59:59").getTime()); -------------------------------------------------------------------------------- /pythonpro/core/static/svg/spp/blue-arrow-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/core/static/svg/spp/green-arrow-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/core/static/svg/spp/green-camera-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/core/static/svg/spp/twitter-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/core/static/svg/spp/white-camera-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/core/static/svg/spp/x-price-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/core/static/svg/spp/youtube-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pythonpro/core/templates/400.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block title %}400. Requisição imprópria{% endblock %} 5 | 6 | {% block body %} 7 |
8 |
9 |
10 |

400

11 |

Requisição imprópria

12 |

A requisição enviada não pode ser atendida.

13 |
14 |
15 |
16 | {% endblock body %} 17 | -------------------------------------------------------------------------------- /pythonpro/core/templates/403.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block title %}403. Proibido{% endblock %} 5 | 6 | {% block body %} 7 |
8 |
9 |
10 |

403

11 |

Proibido

12 |

Você não tem permissão para acessar este endereço.

13 | 14 |
15 |
16 |
17 | {% endblock body %} 18 | 19 | -------------------------------------------------------------------------------- /pythonpro/core/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block title %}404. Página não encontrada{% endblock %} 5 | 6 | {% block body %} 7 |
8 |
9 |
10 |

404

11 |

Página não encontrada

12 |

O endereço que você solicitou não existe.

13 | 14 |
15 |
16 |
17 | {% endblock body %} 18 | -------------------------------------------------------------------------------- /pythonpro/core/templates/500.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block title %}500. Erro interno inesperado{% endblock %} 5 | 6 | {% block body %} 7 |
8 |
9 |
10 |

500

11 |

Erro interno inesperado

12 |

Desculpe. Ocorreu um erro inesperado.

13 |

Nossa equipe já foi notificada do problema.
14 | Caso necessário entre em contato com suporte@dev.pro.br 16 |

17 |
18 |
19 |
20 | {% endblock body %} 21 | -------------------------------------------------------------------------------- /pythonpro/core/templates/core/base_without_nav.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% block navbar %}{% endblock %} 3 | -------------------------------------------------------------------------------- /pythonpro/core/templates/core/lead_landing_lite_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/lead_landing_page.html' %} 2 | 3 | {% block extracontent %}{% endblock %} -------------------------------------------------------------------------------- /pythonpro/core/templates/core/password_email.txt: -------------------------------------------------------------------------------- 1 | Olá {{first_name}}, 2 | 3 | A sua senha para acessar o sistema Dev Pro é: 4 | 5 | {{password}} 6 | 7 | Se quiser alterar sua senha, acesse: 8 | 9 | {{change_password_uri}} 10 | 11 | Grande abraço, 12 | Renzo -------------------------------------------------------------------------------- /pythonpro/core/templates/core/profile_detail.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block title %}Perfil{% endblock %} 5 | 6 | {% block body %} 7 |
8 |
9 |
10 |

Perfil de {{ user.first_name }}

11 |
12 | Editar: Nome 13 | - Email 14 | - Senha 15 | - Autenticação em 2 passos 16 |
17 |
Nome
18 |
19 | {{ user.first_name }} 20 |
21 |
Email
22 |
23 | {{ user.email }} 24 |
25 |
26 |
27 |
28 | {% endblock body %} 29 | -------------------------------------------------------------------------------- /pythonpro/core/templates/core/unsubscribe.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block title %}Descastratamento{% endblock %} 5 | 6 | {% block body %} 7 |
8 |
9 |
10 |

Descadastramento feito com sucesso!

11 |

É uma pena ver você deixar de acompanhar meu conteúdo.

12 |

Mas integridade é o principal valor aqui dentro do Dev Pro. Então respeito completamente sua 13 | decisão.

14 |

E se precisar, você já sabe onde encontrar conteúdo de técnico de qualidade.

15 |

Desejo sucesso em sua jornada.

16 |

Grande Abraço,
17 | Renzo 18 |

19 |
20 |
21 |
22 | {% endblock body %} 23 | -------------------------------------------------------------------------------- /pythonpro/core/templates/registration/password_reset_complete.html: -------------------------------------------------------------------------------- 1 | {% extends "core/base.html" %} 2 | {% block body %} 3 |
4 |
5 |
6 |

Redefinição de senha completa

7 |

Agora você pode usar sua nova senha para acessar o site

8 | Entrar 9 |
10 |
11 |
12 | {% endblock body %} -------------------------------------------------------------------------------- /pythonpro/core/templates/registration/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends "core/base.html" %} 2 | 3 | {% block body %} 4 |
5 |
6 |
7 |

Redefinição de senha enviada

8 | 9 |

Nós te enviamos por e-mail as instruções para redefinição de sua senha, se existir uma conta com o e-mail que 10 | você forneceu. Você receberá a mensagem em breve.

11 | 12 |

Se você não receber um e-mail, por favor verifique se você digitou o endereço que você usou para se 13 | registrar, 14 | e verificar a sua pasta de spam.

15 | 16 |
17 |
18 |
19 | 20 | {% endblock body %} -------------------------------------------------------------------------------- /pythonpro/core/templates/two_factor/_base.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% block body %} 3 |
4 |
5 |
6 | {% block content %}{% endblock %} 7 |
8 |
9 |
10 | 11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /pythonpro/core/templates/two_factor/core/otp_required.html: -------------------------------------------------------------------------------- 1 | {% extends "two_factor/_base_focus.html" %} 2 | {% load i18n %} 3 | 4 | {% block content %} 5 |

{% block title %}{% trans "Permission Denied" %}{% endblock %}

6 | 7 |

{% blocktrans trimmed %}The page you requested, enforces users to verify using 8 | two-factor authentication for security reasons. You need to enable these 9 | security features in order to access this page.{% endblocktrans %}

10 | 11 |

Autenticação em 2 passos não está ativa em sua conta.
12 | Habilite para melhorar a segurança de dua conta.

13 |

14 | {% trans "Go back" %} 16 | 17 | {% trans "Enable Two-Factor Authentication" %} 18 |

19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /pythonpro/core/templates/two_factor/core/setup_complete.html: -------------------------------------------------------------------------------- 1 | {% extends "two_factor/_base_focus.html" %} 2 | {% load i18n %} 3 | 4 | {% block content %} 5 |

{% block title %}{% trans "Enable Two-Factor Authentication" %}{% endblock %}

6 | 7 |

Parabéns, você habilitou a autenticação em 2 passos!

8 | 9 | {% if not phone_methods %} 10 |

Acessar Dashboard

12 | {% else %} 13 |

{% blocktrans trimmed %}However, it might happen that you don't have access to 14 | your primary token device. To enable account recovery, add a phone 15 | number.{% endblocktrans %}

16 | 17 | {% trans "Back to Profile" %} 19 |

{% trans "Add Phone Number" %}

21 | {% endif %} 22 | 23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /pythonpro/core/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/core/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/core/tests/test_linktree.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django.urls import reverse 3 | 4 | 5 | @pytest.fixture 6 | def resp(client): 7 | return client.get(reverse('core:linktree')) 8 | 9 | 10 | def test_status_code(resp): 11 | assert 200 == resp.status_code 12 | -------------------------------------------------------------------------------- /pythonpro/core/tests/test_login.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django.urls import reverse 3 | 4 | 5 | @pytest.fixture 6 | def login_get_resp(client, db): 7 | return client.get(reverse('two_factor:login')) 8 | 9 | 10 | def test_page_status(login_get_resp): 11 | login_get_resp.status = 200 12 | -------------------------------------------------------------------------------- /pythonpro/core/tests/test_password_reset.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django.urls import reverse 3 | 4 | from pythonpro.django_assertions import dj_assert_contains 5 | 6 | 7 | @pytest.fixture 8 | def reset_password_resp(client): 9 | return client.get(reverse('password_reset')) 10 | 11 | 12 | def test_email_form_status(reset_password_resp): 13 | reset_password_resp.status = 200 14 | 15 | 16 | @pytest.mark.parametrize( 17 | 'content', 18 | [ 19 | ' bool: 7 | """ 8 | Indicates if a user has watched any topic 9 | :param: user 10 | :return: boolean 11 | """ 12 | return TopicInteraction.objects.filter(user=user).exists() 13 | -------------------------------------------------------------------------------- /pythonpro/dashboard/forms.py: -------------------------------------------------------------------------------- 1 | from django.forms import ModelForm 2 | 3 | from pythonpro.dashboard.models import TopicInteraction 4 | 5 | 6 | class TopicInteractionForm(ModelForm): 7 | class Meta: 8 | model = TopicInteraction 9 | fields = ('topic', 'user', 'topic_duration', 'total_watched_time', 'max_watched_time') 10 | -------------------------------------------------------------------------------- /pythonpro/dashboard/migrations/0002_auto_20190812_1627.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-08-12 19:27 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('dashboard', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelOptions( 14 | name='topicinteraction', 15 | options={'verbose_name': 'Interação', 'verbose_name_plural': 'Interações'}, 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pythonpro/dashboard/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/dashboard/migrations/__init__.py -------------------------------------------------------------------------------- /pythonpro/dashboard/static/dashboard/img/assinatura-renzo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/dashboard/static/dashboard/img/assinatura-renzo.jpg -------------------------------------------------------------------------------- /pythonpro/dashboard/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/dashboard/templatetags/__init__.py -------------------------------------------------------------------------------- /pythonpro/dashboard/templatetags/dashboard_tags.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | 4 | def duration(value): 5 | try: 6 | duration = int(value) 7 | except ValueError: 8 | return '' 9 | else: 10 | minutes, seconds = divmod(duration, 60) 11 | hours, minutes = divmod(minutes, 60) 12 | if hours > 0: 13 | output = f'{hours:02d} hora(s) {minutes:02d} minuto(s)s {seconds:02d} segundo(s)' 14 | else: 15 | output = f'{minutes:02d} minuto(s)s {seconds:02d} segundo(s)' 16 | return output 17 | 18 | 19 | register = template.Library() 20 | register.filter('duration', duration) 21 | -------------------------------------------------------------------------------- /pythonpro/dashboard/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/dashboard/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/dashboard/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'dashboard' 6 | urlpatterns = [ 7 | path('topic_interaction', views.topic_interaction, name='topic_interaction'), 8 | path('', views.home, name='home'), 9 | path('certificados/', views.certificate, name='certificate'), 10 | ] 11 | -------------------------------------------------------------------------------- /pythonpro/discord/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/discord/__init__.py -------------------------------------------------------------------------------- /pythonpro/discord/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class DiscordConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'pythonpro.discord' 7 | -------------------------------------------------------------------------------- /pythonpro/discord/bot.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | from pythonpro.discord.api_client import DiscordBotClient 4 | 5 | 6 | class _DevProDiscordBotClient(DiscordBotClient): 7 | """ 8 | This class provides data respective to specific seetings for DevPro Discord Guild 9 | """ 10 | 11 | def send_to_sales_channel(self, msg: str) -> dict: 12 | return self.create_message(settings.DISCORD_GUILD_SALES_CHANNEL_ID, msg) 13 | 14 | def send_to_checkout_channel(self, msg: str) -> dict: 15 | return self.create_message(settings.DISCORD_GUILD_SALES_CHANNEL_ID, msg) 16 | 17 | 18 | devpro_discord_bot_client = _DevProDiscordBotClient(settings.DISCORD_APP_BOT_TOKEN) 19 | -------------------------------------------------------------------------------- /pythonpro/discord/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/discord/management/__init__.py -------------------------------------------------------------------------------- /pythonpro/discord/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/discord/management/commands/__init__.py -------------------------------------------------------------------------------- /pythonpro/discord/management/commands/clean_discord_users.py: -------------------------------------------------------------------------------- 1 | from django.core.management import BaseCommand 2 | 3 | from pythonpro.discord import facade 4 | 5 | 6 | class Command(BaseCommand): 7 | help = 'Sincronizar usuários do Discord com Painel da DevPro' 8 | 9 | def add_arguments(self, parser): 10 | pass 11 | 12 | def handle(self, *args, **options): 13 | facade.clean_discord_users() 14 | -------------------------------------------------------------------------------- /pythonpro/discord/management/commands/warn_users_about_subscription_expiration.py: -------------------------------------------------------------------------------- 1 | from django.core.management import BaseCommand 2 | 3 | from pythonpro.discord import facade 4 | 5 | 6 | class Command(BaseCommand): 7 | help = 'Sincronizar usuários do Discord com Painel da DevPro' 8 | 9 | def add_arguments(self, parser): 10 | pass 11 | 12 | def handle(self, *args, **options): 13 | facade.warn_users_about_subscription_expiration() 14 | -------------------------------------------------------------------------------- /pythonpro/discord/migrations/0002_discord_user_created_at_desc_index.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.1 on 2022-09-14 10:48 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ('discord', '0001_initial'), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddIndex( 13 | model_name='discorduser', 14 | index=models.Index(fields=['-created_at'], name='discord_created_at_desc_index'), 15 | ), 16 | ] 17 | -------------------------------------------------------------------------------- /pythonpro/discord/migrations/0003_create_discord_lead.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.10 on 2024-02-28 18:04 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('discord', '0002_discord_user_created_at_desc_index'), 10 | ] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name='DiscordLead', 15 | fields=[ 16 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 17 | ('discord_id', models.CharField(max_length=64, unique=True)), 18 | ('created_at', models.DateTimeField(auto_now_add=True)), 19 | ('updated_at', models.DateTimeField(auto_now=True)), 20 | ('status', models.CharField(choices=[('A', 'Ativa'), ('I', 'Inativa')], default='I', max_length=32)), 21 | ], 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pythonpro/discord/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/discord/migrations/__init__.py -------------------------------------------------------------------------------- /pythonpro/discord/templates/discord/access_denied.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block title %}Acesso negado{% endblock %} 5 | 6 | {% block body %} 7 |
8 |
9 |
10 |

Acesso Negado

11 |

Veja como proceder

12 |

Nosso sistema não encontrou acesso válido para sua conta. Entre em contato com o suporte pelo 13 | email {{ DEFAULT_FROM_EMAIL }}.

14 | 15 |
16 |
17 |
18 | {% endblock body %} -------------------------------------------------------------------------------- /pythonpro/discord/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/discord/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/discord/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from pythonpro.discord import views 4 | 5 | app_name = 'discord' 6 | urlpatterns = [ 7 | path('autorize', views.autorize, name='autorize'), 8 | ] 9 | -------------------------------------------------------------------------------- /pythonpro/discourse/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/discourse/__init__.py -------------------------------------------------------------------------------- /pythonpro/discourse/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class PromosConfig(AppConfig): 5 | name = 'pythonpro.discourse' 6 | verbose_name = 'Discourse Forum Integration' 7 | -------------------------------------------------------------------------------- /pythonpro/discourse/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/discourse/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/discourse/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from pythonpro.discourse import views 4 | 5 | app_name = 'discourse' 6 | urlpatterns = [ 7 | path('login/', views.sso, name='sso'), 8 | ] 9 | -------------------------------------------------------------------------------- /pythonpro/discourse/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.decorators import login_required 2 | from django.http import HttpResponseRedirect 3 | from django.views.defaults import bad_request 4 | 5 | from pythonpro.discourse.facade import InvalidSOOPayload, generate_discourse_login_url 6 | 7 | 8 | @login_required 9 | def sso(request): 10 | """ 11 | Proceed login into discourse 12 | 13 | Code based on https://meta.discourse.org/t/sso-example-for-django/14258 14 | """ 15 | payload = request.GET.get('sso') 16 | signature = request.GET.get('sig') 17 | try: 18 | url = generate_discourse_login_url(request.user, payload, signature) 19 | except InvalidSOOPayload as e: 20 | return bad_request(request, e) 21 | else: 22 | return HttpResponseRedirect(url) 23 | -------------------------------------------------------------------------------- /pythonpro/django_assertions.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Module to expose Django's TestCase assertions as functions 3 | ''' 4 | from django.test import TestCase 5 | 6 | _dj_testcase = TestCase() 7 | 8 | dj_assert_contains = _dj_testcase.assertContains 9 | dj_assert_not_contains = _dj_testcase.assertNotContains 10 | dj_assert_template_used = _dj_testcase.assertTemplateUsed 11 | dj_assert_redirects = _dj_testcase.assertRedirects 12 | -------------------------------------------------------------------------------- /pythonpro/domain/README.md: -------------------------------------------------------------------------------- 1 | This package contains all facades containing entire application business rules (domain) -------------------------------------------------------------------------------- /pythonpro/domain/__init__.py: -------------------------------------------------------------------------------- 1 | from pythonpro.domain import (checkout_domain, content_statistics_domain, user_domain) 2 | 3 | __all__ = [ 4 | 'content_statistics_domain', 5 | 'user_domain', 6 | 'checkout_domain' 7 | ] 8 | -------------------------------------------------------------------------------- /pythonpro/domain/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/domain/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/domain/tests/test_checkout/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/domain/tests/test_checkout/__init__.py -------------------------------------------------------------------------------- /pythonpro/domain/tests/test_checkout/test_payment_page.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django.urls import reverse 3 | 4 | from pythonpro.domain.tests.test_checkout.conftest import ALL_PRODUCTS 5 | 6 | 7 | @pytest.mark.parametrize('slug', ALL_PRODUCTS) 8 | def test_all_slugs_available(client, slug): 9 | if not slug.startswith('bootcamp-webdev'): 10 | resp = client.get(reverse('django_pagarme:pagarme', kwargs={'slug': slug})) 11 | assert resp.status_code == 200 12 | -------------------------------------------------------------------------------- /pythonpro/domain/tests/test_checkout/test_thanks.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django.urls import reverse 3 | 4 | from pythonpro.domain.tests.test_checkout.conftest import ALL_ACTIVE_PRODUCTS 5 | 6 | 7 | @pytest.mark.parametrize('slug', ALL_ACTIVE_PRODUCTS) 8 | def test_all_slugs_available(client, slug): 9 | resp = client.get(reverse('django_pagarme:thanks', kwargs={'slug': slug})) 10 | assert resp.status_code == 200 11 | -------------------------------------------------------------------------------- /pythonpro/email_marketing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/email_marketing/__init__.py -------------------------------------------------------------------------------- /pythonpro/email_marketing/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class EmailMarketing(AppConfig): 5 | name = 'pythonpro.email_marketing' 6 | -------------------------------------------------------------------------------- /pythonpro/launch/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/launch/__init__.py -------------------------------------------------------------------------------- /pythonpro/launch/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class LaunchConfig(AppConfig): 5 | name = 'pythonpro.launch' 6 | -------------------------------------------------------------------------------- /pythonpro/launch/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.forms.utils import ErrorList 3 | 4 | 5 | class LeadForm(forms.Form): 6 | name = forms.CharField(required=True) 7 | email = forms.EmailField(required=True) 8 | 9 | def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=ErrorList, 10 | label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, 11 | renderer=None): 12 | super().__init__(data, files, auto_id, prefix, initial, error_class, label_suffix, empty_permitted, field_order, 13 | use_required_attribute, renderer) 14 | self._normalize_email() 15 | 16 | def _normalize_email(self): 17 | self.data = dict(self.data.items()) 18 | email = self.data.get('email') 19 | if email is not None: 20 | self.data['email'] = email.lower() 21 | -------------------------------------------------------------------------------- /pythonpro/launch/templates/launch/membership_email.txt: -------------------------------------------------------------------------------- 1 | Olá {{ user.first_name }}, 2 | 3 | Recebemos a confirmação de seu pagamento para a próxima turma Dev Pro. 4 | 5 | Faça login com sua conta e acesse a página de detalhes da turma em {{ cohort_detail_url }} para conferir as datas das atividades. 6 | 7 | Nessa página também existem as informações para vc se apresentar no fórum e também acessar nosso badalado grupo do Telegram! 8 | 9 | Agradecemos imensamente sua confiança em nosso trabalho. 10 | 11 | Grande abraço, 12 | Renzo Nuccitelli -------------------------------------------------------------------------------- /pythonpro/launch/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/launch/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/launch/tests/test_ty.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django.urls import reverse 3 | 4 | from pythonpro.django_assertions import dj_assert_contains 5 | from pythonpro.domain.user_domain import find_user_interactions 6 | 7 | 8 | @pytest.fixture 9 | def resp(client, cohort): 10 | return client.get(reverse('launch:ty')) 11 | 12 | 13 | def test_status_code(resp): 14 | assert 200 == resp.status_code 15 | 16 | 17 | @pytest.mark.parametrize( 18 | 'media_link', 19 | [ 20 | 'https://twitter.com/renzoprobr', 21 | 'https://www.youtube.com/user/renzonuccitelli', 22 | 'https://instagram.com/renzoprobr', 23 | ] 24 | 25 | ) 26 | def test_email_field_is_present(resp, media_link): 27 | dj_assert_contains(resp, media_link) 28 | 29 | 30 | @pytest.fixture 31 | def resp_with_user(client_with_user, cohort): 32 | return client_with_user.get(reverse('launch:ty')) 33 | 34 | 35 | def test_user_interaction(resp_with_user, logged_user): 36 | assert 'LAUNCH_SUBSCRIPTION' in [i.category for i in find_user_interactions(logged_user)] 37 | -------------------------------------------------------------------------------- /pythonpro/launch/tests/test_vip_list.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django.urls import reverse 3 | 4 | from pythonpro.django_assertions import dj_assert_contains 5 | 6 | 7 | @pytest.fixture 8 | def resp(client): 9 | return client.get(reverse('launch:vip_list')) 10 | 11 | 12 | def test_status_code(resp): 13 | assert 200 == resp.status_code 14 | 15 | 16 | def test_email_field_is_present(resp): 17 | dj_assert_contains(resp, 'https://python.activehosted.com/f/embed.php?id=2') 18 | -------------------------------------------------------------------------------- /pythonpro/memberkit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/memberkit/__init__.py -------------------------------------------------------------------------------- /pythonpro/memberkit/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class MemberkitConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'pythonpro.memberkit' 7 | -------------------------------------------------------------------------------- /pythonpro/memberkit/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/memberkit/management/__init__.py -------------------------------------------------------------------------------- /pythonpro/memberkit/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/memberkit/management/commands/__init__.py -------------------------------------------------------------------------------- /pythonpro/memberkit/management/commands/inactivate_expired_subscriptions.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | 3 | from pythonpro.memberkit import facade 4 | 5 | 6 | class Command(BaseCommand): 7 | help = 'Busca todas assinaturas ativas e inativa as que estão expiradas' 8 | 9 | def add_arguments(self, parser): 10 | pass 11 | 12 | def handle(self, *args, **options): 13 | facade.inactivate_expired_subscriptions() 14 | -------------------------------------------------------------------------------- /pythonpro/memberkit/management/commands/synchronize_paid_subscriptions.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand 2 | from django_pagarme import facade as pagarme_facade 3 | from django_pagarme.models import PagarmePayment 4 | 5 | from pythonpro.memberkit import facade 6 | 7 | 8 | class Command(BaseCommand): 9 | help = 'Cria Assinatura para pagamentos que já tiveram status pago' 10 | 11 | def add_arguments(self, parser): 12 | pass 13 | 14 | def handle(self, *args, **options): 15 | for payment in PagarmePayment.objects.filter(notifications__status=pagarme_facade.PAID, subscription=None): 16 | self.stdout.write(self.style.SUCCESS(f'Processando pagamento {payment}')) 17 | facade.create_new_subscription(payment, 'Criado através de comando de sincronização') 18 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.4 on 2021-06-03 20:51 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | initial = True 8 | 9 | dependencies = [ 10 | ] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name='SubscriptionType', 15 | fields=[ 16 | ('id', models.IntegerField(primary_key=True, serialize=False, unique=True)), 17 | ('name', models.CharField(max_length=128)), 18 | ], 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/0004_add_membership_activation_data.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.4 on 2021-06-09 17:38 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ('memberkit', '0003_subscription'), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name='subscription', 14 | name='activated_at', 15 | field=models.DateTimeField(default=None, null=True), 16 | ), 17 | migrations.AddField( 18 | model_name='subscription', 19 | name='memberkit_user_id', 20 | field=models.IntegerField(null=True), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/0005_create_tags_for_discourse_email_marketing_subscription.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.4 on 2021-06-10 00:41 2 | 3 | import django.contrib.postgres.fields 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ('memberkit', '0004_add_membership_activation_data'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='subscriptiontype', 15 | name='discourse_groups', 16 | field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=64), default=list, 17 | size=None), 18 | ), 19 | migrations.AddField( 20 | model_name='subscriptiontype', 21 | name='email_marketing_tags', 22 | field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=64), default=list, 23 | size=None), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/0006_include_cohort_subscription_flag.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.4 on 2021-06-10 01:14 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('memberkit', '0005_create_tags_for_discourse_email_marketing_subscription'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='subscriptiontype', 15 | name='include_on_cohort', 16 | field=models.BooleanField(default=False, verbose_name='Incluir na última turma'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/0007_allow_subscripiton_be_saved_without_payment.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.4 on 2021-06-10 02:08 2 | 3 | import django.db.models.deletion 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | dependencies = [ 9 | ('django_pagarme', '0005_change_primary_key_to_big_integer'), 10 | ('memberkit', '0006_include_cohort_subscription_flag'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='subscription', 16 | name='payment', 17 | field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, 18 | to='django_pagarme.pagarmepayment'), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/0008_added_days_of_access_field.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.7 on 2021-09-15 01:24 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ('memberkit', '0007_allow_subscripiton_be_saved_without_payment'), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name='subscription', 14 | name='days_of_access', 15 | field=models.IntegerField(default=73000), 16 | ), 17 | migrations.AddField( 18 | model_name='subscriptiontype', 19 | name='days_of_access', 20 | field=models.IntegerField(default=73000), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/0009_altered_subscription_default_to_one_year.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.4 on 2022-05-26 19:15 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [('memberkit', '0008_added_days_of_access_field')] 8 | 9 | operations = [ 10 | migrations.AlterField( 11 | model_name='subscription', 12 | name='days_of_access', 13 | field=models.IntegerField(default=365), 14 | ), 15 | migrations.AlterField( 16 | model_name='subscriptiontype', 17 | name='days_of_access', 18 | field=models.IntegerField(default=365), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/0010_added_has_discord_access.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-09-01 00:13 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ('memberkit', '0009_altered_subscription_default_to_one_year'), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name='subscriptiontype', 14 | name='has_discord_access', 15 | field=models.BooleanField(default=False), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/0011_alter_subscription_status.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-03-23 02:32 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ('memberkit', '0010_added_has_discord_access'), 9 | ] 10 | 11 | operations = [ 12 | migrations.AlterField( 13 | model_name='subscription', 14 | name='status', 15 | field=models.CharField(choices=[('A', 'Ativa'), ('I', 'Inativa')], max_length=1), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/0012_added_subscription_expired_at.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-04-12 23:17 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ('memberkit', '0011_alter_subscription_status'), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name='subscription', 14 | name='expired_at', 15 | field=models.DateField(null=True), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/0014_alter_subscription_days_of_access_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.7 on 2023-04-13 00:58 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ('memberkit', '0013_populate_expired_at'), 9 | ] 10 | 11 | operations = [ 12 | migrations.AlterField( 13 | model_name='subscription', 14 | name='days_of_access', 15 | field=models.IntegerField(db_column='days_of_access', default=365), 16 | ), 17 | migrations.RenameField( 18 | model_name='subscription', 19 | old_name='days_of_access', 20 | new_name='old_days_of_access', 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /pythonpro/memberkit/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/memberkit/migrations/__init__.py -------------------------------------------------------------------------------- /pythonpro/memberkit/templates/memberkit/manual_migration.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base_without_nav.html' %} 2 | {% load static %} 3 | 4 | {% block title %}Migração para nova plataforma{% endblock %} 5 | 6 | {% block body %} 7 |
8 |
9 |
10 |

Migração com problemas

11 |

12 |

Olá {{ request.user.first_name }}.

13 |

Infelizmente a sua migração não aconteceu automaticamente.

14 |

Um email já foi enviado para resolvermos. Mas você pode adiantar o processo entrando em contato com o 15 | Renzo no Telegram e avisando que isso aconteceu. Informe seu email na 16 | mensagem: {{ request.user.email }}.

17 |
18 |
19 |
20 | {% endblock body %} 21 | -------------------------------------------------------------------------------- /pythonpro/memberkit/templates/memberkit/subscriptiontype/synchronize_button.html: -------------------------------------------------------------------------------- 1 | {% extends 'admin/change_list.html' %} 2 | 3 | {% block object-tools %} 4 |
5 |
6 | {% csrf_token %} 7 | 8 |
9 |
10 |
11 | {{ block.super }} 12 | {% endblock %} -------------------------------------------------------------------------------- /pythonpro/memberkit/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/memberkit/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/memberkit/tests/test_subscription_summary.py: -------------------------------------------------------------------------------- 1 | from model_bakery import baker 2 | 3 | from pythonpro.memberkit.models import UserSubscriptionsSummary, Subscription 4 | 5 | 6 | def test_user_summary_with_no_subscriptions(logged_user): 7 | summary = UserSubscriptionsSummary(logged_user) 8 | assert not summary.has_active_subscriptions() 9 | 10 | 11 | def test_user_with_active_subscriptions(django_user_model): 12 | active_users = baker.make(django_user_model, 5) 13 | for active_user in active_users: 14 | baker.make(Subscription, status=Subscription.Status.ACTIVE, subscriber=active_user) 15 | 16 | inactive_users = baker.make(django_user_model, 5) 17 | for inactive_user in inactive_users: 18 | baker.make(Subscription, status=Subscription.Status.INACTIVE, subscriber=inactive_user) 19 | 20 | active_user_ids_from_db = set( 21 | UserSubscriptionsSummary.users_with_active_subscriptions().values_list('id', flat=True) 22 | ) 23 | assert active_user_ids_from_db == set(active_user.id for active_user in active_users) 24 | -------------------------------------------------------------------------------- /pythonpro/memberkit/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.decorators import login_required 2 | from django.core.mail import mail_admins 3 | from django.shortcuts import redirect, render 4 | 5 | from pythonpro.memberkit import facade 6 | 7 | 8 | @login_required 9 | def migrate_to_memberkit(request): 10 | user = request.user 11 | facade.migrate_when_status_active(user) 12 | try: 13 | login_url = facade.create_login_url(user) 14 | except facade.InactiveUserException: 15 | mail_admins( 16 | f'Verificar migração de {user.email}', 17 | f'Link: https://painel.dev.pro.br/admin/memberkit/subscription/?q={user.email}' 18 | ) 19 | return render(request, 'memberkit/manual_migration.html') 20 | else: 21 | return redirect(login_url) 22 | -------------------------------------------------------------------------------- /pythonpro/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/modules/__init__.py -------------------------------------------------------------------------------- /pythonpro/modules/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ModulesConfig(AppConfig): 5 | name = 'pythonpro.modules' 6 | -------------------------------------------------------------------------------- /pythonpro/modules/chapters_urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from pythonpro.modules import chapters_views 4 | 5 | app_name = 'chapters' 6 | urlpatterns = [ 7 | path('/', chapters_views.detail_old, name='detail_old'), 8 | ] 9 | -------------------------------------------------------------------------------- /pythonpro/modules/chapters_views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.decorators import login_required 2 | from django.shortcuts import render, redirect 3 | 4 | from pythonpro.modules import facade 5 | 6 | 7 | @login_required 8 | def detail_old(request, chapter_slug): 9 | chapter = facade.get_chapter_with_contents(slug=chapter_slug) 10 | return redirect(chapter.get_absolute_url(), permanent=True) 11 | 12 | 13 | @login_required 14 | def detail(request, module_slug, chapter_slug): 15 | ctx = {'chapter': facade.get_chapter_with_contents(slug=chapter_slug)} 16 | return render(request, 'chapters/chapter_detail.html', context=ctx) 17 | -------------------------------------------------------------------------------- /pythonpro/modules/context_processors.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | from pythonpro.modules.facade import get_all_modules 4 | 5 | 6 | def global_settings(request): 7 | # return any necessary values 8 | if not request.user.is_authenticated: 9 | return {} 10 | 11 | return { 12 | 'ALL_MODULES': get_all_modules(), 13 | 'SENTRY_DSN': settings.SENTRY_DSN, 14 | } 15 | -------------------------------------------------------------------------------- /pythonpro/modules/migrations/0002_auto_20180314_1122.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.3 on 2018-03-14 14:22 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('modules', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelTable( 14 | name='section', 15 | table=None, 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pythonpro/modules/migrations/0003_module.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.3 on 2018-03-14 17:38 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('modules', '0002_auto_20180314_1122'), 10 | ] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name='Module', 15 | fields=[ 16 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 17 | ('order', models.PositiveIntegerField(db_index=True, editable=False)), 18 | ('title', models.CharField(max_length=50)), 19 | ('description', models.TextField()), 20 | ('slug', models.SlugField(unique=True)), 21 | ('objective', models.TextField()), 22 | ('target', models.TextField()), 23 | ], 24 | options={ 25 | 'ordering': ('order',), 26 | 'abstract': False, 27 | }, 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /pythonpro/modules/migrations/0005_auto_20180314_1817.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.3 on 2018-03-14 21:17 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('modules', '0004_section_module'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelOptions( 14 | name='section', 15 | options={'ordering': ['module', 'order']}, 16 | ), 17 | migrations.RemoveField( 18 | model_name='section', 19 | name='_module_slug', 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /pythonpro/modules/migrations/0006_chapter.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.3 on 2018-03-17 16:03 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('modules', '0005_auto_20180314_1817'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Chapter', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('order', models.PositiveIntegerField(db_index=True, editable=False)), 19 | ('title', models.CharField(max_length=50)), 20 | ('description', models.TextField()), 21 | ('slug', models.SlugField(unique=True)), 22 | ('section', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='modules.Section')), 23 | ], 24 | options={ 25 | 'ordering': ['section', 'order'], 26 | }, 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /pythonpro/modules/migrations/0008_topic_discourse_topic_id.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.3 on 2018-03-19 03:18 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ('modules', '0007_topic'), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name='topic', 14 | name='discourse_topic_id', 15 | field=models.CharField(default='1', max_length=11), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pythonpro/modules/migrations/0009_auto_20180319_0020.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.3 on 2018-03-19 03:20 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ('modules', '0008_topic_discourse_topic_id'), 9 | ] 10 | 11 | operations = [ 12 | migrations.AlterField( 13 | model_name='topic', 14 | name='discourse_topic_id', 15 | field=models.CharField(max_length=11), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pythonpro/modules/migrations/0011_created_duration_on_topic.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.2 on 2020-01-31 11:53 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('modules', '0010_auto_20190226_1830'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='topic', 15 | name='duration', 16 | field=models.IntegerField(default=0), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pythonpro/modules/migrations/0012_create_memberkit_url.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.3 on 2021-05-26 23:54 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ('modules', '0011_created_duration_on_topic'), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name='topic', 14 | name='memberkit_url', 15 | field=models.URLField(blank=True, default='', max_length=1024), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pythonpro/modules/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/modules/migrations/__init__.py -------------------------------------------------------------------------------- /pythonpro/modules/module_urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import modules_views, sections_views, topics_views, chapters_views 4 | 5 | app_name = 'modules' 6 | urlpatterns = [ 7 | path('', modules_views.index, name='index'), 8 | path('/', modules_views.detail, name='detail'), 9 | path('enrol//', modules_views.enrol, name='enrol'), 10 | path('/topicos/', topics_views.detail, name='topic_detail'), 11 | path('/secoes/', sections_views.detail, name='section_detail'), 12 | path('/capitulos/', chapters_views.detail, name='chapter_detail'), 13 | path('descricao//', modules_views.description, name='description'), 14 | ] 15 | -------------------------------------------------------------------------------- /pythonpro/modules/permissions.py: -------------------------------------------------------------------------------- 1 | from rolepermissions.permissions import register_object_checker 2 | 3 | from pythonpro.modules.models import Content 4 | 5 | 6 | @register_object_checker() 7 | def access_content(role, user, content: Content) -> bool: 8 | module_slug = content.module_slug() 9 | return module_slug == 'python-birds' 10 | -------------------------------------------------------------------------------- /pythonpro/modules/sections_urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from pythonpro.modules import sections_views 4 | 5 | app_name = 'sections' 6 | urlpatterns = [ 7 | path('/', sections_views.detail_old, name='detail_old'), 8 | ] 9 | -------------------------------------------------------------------------------- /pythonpro/modules/sections_views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.decorators import login_required 2 | from django.shortcuts import redirect, render 3 | 4 | from pythonpro.modules import facade 5 | 6 | 7 | @login_required 8 | def detail_old(request, slug): 9 | section = facade.get_section_with_contents(slug=slug) 10 | return redirect(section.get_absolute_url(), permanent=True) 11 | 12 | 13 | @login_required 14 | def detail(request, module_slug, section_slug): 15 | ctx = {'section': facade.get_section_with_contents(slug=section_slug)} 16 | return render(request, 'sections/section_detail.html', ctx) 17 | -------------------------------------------------------------------------------- /pythonpro/modules/templates/modules/module_enrol.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block title %}Começar metas do módulo {{ module.title }}{% endblock %} 5 | {% block description %}Expliação de sistema de metas do módulo {{ topic.description }}{% endblock %} 6 | {% block body %} 7 |
8 |
9 |
10 |

Metas ativadas para o módulo {{ module.title }}

11 |

Você receberá emails semanais para te ajudar a terminar esse módulo. Serão 4 semanas no total

12 |

Em instantes você já receberá o primeiro. Confira sua caixa de spam

13 |
14 |
15 |
16 | {% endblock body %} 17 | -------------------------------------------------------------------------------- /pythonpro/modules/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/modules/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/modules/topics_urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from pythonpro.modules import topics_views 4 | 5 | app_name = 'topics' 6 | urlpatterns = [ 7 | path('/', topics_views.old_detail, name='detail_old'), 8 | ] 9 | -------------------------------------------------------------------------------- /pythonpro/pages/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/pages/__init__.py -------------------------------------------------------------------------------- /pythonpro/pages/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class PagesConfig(AppConfig): 5 | name = 'pythonpro.pages' 6 | -------------------------------------------------------------------------------- /pythonpro/pages/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | 4 | class NameEmailForm(forms.Form): 5 | name = forms.CharField(label='', widget=forms.TextInput(attrs={'placeholder': 'Insira seu Nome'})) 6 | email = forms.EmailField(label='', widget=forms.TextInput(attrs={'placeholder': 'Insira seu Email'})) 7 | 8 | 9 | class NameEmailPhoneForm(NameEmailForm): 10 | phone = forms.CharField( 11 | label='', 12 | widget=forms.TextInput(attrs={'placeholder': 'Insira seu WhatsApp (não se esqueça do DDD)'}) 13 | ) 14 | 15 | def clean_phone(self): 16 | phone = self.cleaned_data['phone'] 17 | phone = phone.replace('(', '') 18 | phone = phone.replace(')', '') 19 | phone = phone.replace(' ', '') 20 | phone = phone.replace('-', '') 21 | return phone 22 | -------------------------------------------------------------------------------- /pythonpro/pages/templates/pages/pixeling_page.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | 3 | {% block navbar %}{% endblock %} 4 | {% block footer %}{% endblock %} 5 | 6 | -------------------------------------------------------------------------------- /pythonpro/pages/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/pages/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/pages/tests/test_leads_onboarding_page.py: -------------------------------------------------------------------------------- 1 | from django.urls import reverse 2 | 3 | 4 | def test_should_return_200_when_load_invite_page(client): 5 | resp = client.get(reverse('pages:leads_onboarding_page')) 6 | assert resp.status_code == 200 7 | -------------------------------------------------------------------------------- /pythonpro/redirector/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/redirector/__init__.py -------------------------------------------------------------------------------- /pythonpro/redirector/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.utils.html import format_html 3 | 4 | from pythonpro.redirector.models import Redirect, RedirectLink 5 | 6 | 7 | class RedirectLinkAdmin(admin.TabularInline): 8 | model = RedirectLink 9 | extra = 1 10 | readonly_fields = ['total_access', ] 11 | exclude = ['created', 'updated'] 12 | 13 | 14 | @admin.register(Redirect) 15 | class RedirectorAdmin(admin.ModelAdmin): 16 | list_display = ['slug', 'created', 'get_redirect_link'] 17 | list_filter = ['use_javascript', 'created'] 18 | inlines = (RedirectLinkAdmin, ) 19 | exclude = ['created', 'updated'] 20 | ordering = ['-updated', '-created', 'slug'] 21 | 22 | def get_redirect_link(self, obj): 23 | return format_html( 24 | f""" 25 | Link Gerado 26 | """) 27 | 28 | get_redirect_link.short_description = 'Links' 29 | -------------------------------------------------------------------------------- /pythonpro/redirector/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class RedirectorConfig(AppConfig): 5 | name = 'pythonpro.redirector' 6 | -------------------------------------------------------------------------------- /pythonpro/redirector/facade.py: -------------------------------------------------------------------------------- 1 | def _count_access_in_link(link): 2 | link.total_access += 1 3 | link.save() 4 | 5 | 6 | def get_redirect_url(redirect): 7 | if redirect.links.exists(): 8 | link = redirect.links.order_by('total_access', 'id').first() 9 | _count_access_in_link(link) 10 | return link.url 11 | 12 | return redirect.url 13 | -------------------------------------------------------------------------------- /pythonpro/redirector/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.4 on 2020-03-26 03:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Redirect', 16 | fields=[ 17 | ('url', models.URLField()), 18 | ('slug', models.SlugField(primary_key=True, serialize=False)), 19 | ], 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /pythonpro/redirector/migrations/0003_redirect_use_javascript.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.4 on 2020-04-22 00:49 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('redirector', '0002_auto_20200421_2144'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='redirect', 15 | name='use_javascript', 16 | field=models.BooleanField(default=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pythonpro/redirector/migrations/0004_redirectlink_total_access.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.4 on 2020-04-22 01:05 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('redirector', '0003_redirect_use_javascript'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='redirectlink', 15 | name='total_access', 16 | field=models.BigIntegerField(default=0), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pythonpro/redirector/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/redirector/migrations/__init__.py -------------------------------------------------------------------------------- /pythonpro/redirector/models.py: -------------------------------------------------------------------------------- 1 | from django.utils import timezone 2 | from django.db import models 3 | 4 | 5 | class Redirect(models.Model): 6 | created = models.DateTimeField("Criado em", default=timezone.now) 7 | updated = models.DateTimeField("Alterado em", auto_now=True) 8 | slug = models.SlugField(primary_key=True) 9 | url = models.URLField(null=True, blank=True) 10 | use_javascript = models.BooleanField(default=False) 11 | 12 | def __str__(self): 13 | return self.slug 14 | 15 | def get_absolute_url(self): 16 | return f'/r/{self.slug}' 17 | 18 | 19 | class RedirectLink(models.Model): 20 | created = models.DateTimeField("Criado em", default=timezone.now) 21 | updated = models.DateTimeField("Alterado em", auto_now=True) 22 | redirect = models.ForeignKey(Redirect, on_delete=models.PROTECT, related_name='links') 23 | url = models.URLField() 24 | total_access = models.BigIntegerField(default=0) 25 | -------------------------------------------------------------------------------- /pythonpro/redirector/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/redirector/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/redirector/tests/test_redirect_by_headers.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django.urls import reverse 3 | from model_bakery import baker 4 | 5 | from pythonpro.redirector.models import Redirect 6 | 7 | 8 | @pytest.fixture 9 | def redirect(db): 10 | return baker.make(Redirect, url='https://google.com') 11 | 12 | 13 | @pytest.fixture 14 | def resp(client, redirect): 15 | return client.get(reverse('redirector:redirect', kwargs={'slug': redirect.slug})) 16 | 17 | 18 | def test_status_code_should_return_302(resp): 19 | assert resp.status_code == 302 20 | -------------------------------------------------------------------------------- /pythonpro/redirector/tests/test_redirect_by_javascript.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from django.urls import reverse 3 | from model_bakery import baker 4 | 5 | from pythonpro.django_assertions import dj_assert_contains 6 | from pythonpro.redirector.models import Redirect 7 | from pythonpro.redirector.facade import get_redirect_url 8 | 9 | 10 | @pytest.fixture 11 | def redirect(db): 12 | return baker.make(Redirect, url='https://google.com', use_javascript=True) 13 | 14 | 15 | def test_should_redirect_url_in_redirect_object(redirect): 16 | assert get_redirect_url(redirect) == redirect.url 17 | 18 | 19 | @pytest.fixture 20 | def resp(client, redirect): 21 | return client.get(reverse('redirector:redirect', kwargs={'slug': redirect.slug})) 22 | 23 | 24 | def test_status_code_should_return_200(resp): 25 | assert resp.status_code == 200 26 | 27 | 28 | def test_should_redirect_js_contains_redirect_url(resp, redirect): 29 | dj_assert_contains(resp, f'window.location.replace("{redirect.url}")') 30 | -------------------------------------------------------------------------------- /pythonpro/redirector/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from pythonpro.redirector import views 4 | 5 | app_name = 'redirector' 6 | urlpatterns = [ 7 | path('', views.redirect, name='redirect'), 8 | ] 9 | -------------------------------------------------------------------------------- /pythonpro/redirector/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect as redirect_url 2 | 3 | from pythonpro.redirector.models import Redirect 4 | from pythonpro.redirector.facade import get_redirect_url 5 | 6 | 7 | def redirect(request, slug: str): 8 | redirect = Redirect.objects.get(slug=slug) 9 | url = get_redirect_url(redirect) 10 | 11 | if '?' in url and request.GET: 12 | url = f'{url}&{request.GET.urlencode()}' 13 | elif request.GET: 14 | url = f'{url}?{request.GET.urlencode()}' 15 | 16 | if redirect.use_javascript is False: 17 | return redirect_url(url) 18 | 19 | ctx = {'url': url} 20 | return render(request, 'redirector/redirect.html', ctx) 21 | -------------------------------------------------------------------------------- /pythonpro/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pythonprobr/pythonpro-website/cbef22a6e5435fd00200d5481c1378995d562e16/pythonpro/tests/__init__.py -------------------------------------------------------------------------------- /pythonpro/tests/test_urls.py: -------------------------------------------------------------------------------- 1 | from pythonpro.urls import urlpatterns 2 | 3 | 4 | def test_urls_len(): 5 | assert 16 <= len(urlpatterns) 6 | -------------------------------------------------------------------------------- /pythonpro/tests/test_wsgi.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from django.core.handlers.wsgi import WSGIHandler 4 | 5 | from pythonpro.wsgi import application 6 | 7 | 8 | def test_wsgi_default_settings(): 9 | assert 'pythonpro.settings' == os.environ["DJANGO_SETTINGS_MODULE"] 10 | 11 | 12 | def test_application_instace(): 13 | assert isinstance(application, WSGIHandler) 14 | -------------------------------------------------------------------------------- /pythonpro/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for pythonpro project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pythonpro.settings') 15 | 16 | application = get_wsgi_application() 17 | --------------------------------------------------------------------------------