Author SHA1 Message Date
Tirsvad 457b84c6da Add README, screenshots, tri-lingual wiki and wiki workflow (MIL-003)
README from the framework template, three terminal screenshots rendered by
script, wiki pages in English, Danish and Bahasa Malaysia, the publish-wiki
workflow, and the milestone links in the Project Plan.

Refs #13
Refs #14
Refs #15
Refs #16
Refs #17
Refs #18
2026-10-17 15:41:15 +08:00
Tirsvad 5937dc2725 Merge pull request 'MIL-002: birthday wisher core' (#20) from mil-002-birthday-wisher-core into main
TirSystem/github-action: Sync GitHub mirror metadata / sync-metadata (push) Successful in 7s
2026-10-17 09:37:35 +02:00
26 changed files with 523 additions and 4 deletions
+38
View File
@@ -0,0 +1,38 @@
# Publish the project's wiki pages to the git host's wiki.
#
# On a push to main that changes docs/wiki/, this workflow calls the reusable
# workflow of TirSystem/github-action, which copies the Markdown pages of
# docs/wiki/ to the wiki of this repository (framework/process/wiki.md says
# what the folder holds: English and the PO language as a minimum).
#
# INSTALLING THIS FILE IS THE OPT-IN. There is no marker file. A project that
# does not copy it publishes nothing.
#
# Copy it to .gitea/workflows/publish-wiki.yml. Then:
# 1. Create the secret TOKEN_FOR_GITEA_WIKI in the organization of the
# repository: a Gitea token with scope write:repository for a user that
# can write this repository (see guides/credentials.md of github-action).
# 2. Enable the wiki in the repository settings.
# 3. Keep @v1, or pin the exact release tag together with tools-ref.
# A runner must be registered for the repository (or its organization).
#
# prune: "true" deletes wiki pages that are not in docs/wiki/, so the wiki
# always equals the folder. Leave it "false" to keep hand-written pages.
name: Publish wiki
on:
push:
branches: [ main ]
paths:
- "docs/wiki/**"
workflow_dispatch:
jobs:
wiki:
uses: TirSystem/github-action/.gitea/workflows/publish-wiki-pages.yml@v1
with:
wiki_dir: docs/wiki
prune: "true"
secrets:
TOKEN_FOR_GITEA_WIKI: ${{ secrets.TOKEN_FOR_GITEA_WIKI }}
+3
View File
@@ -27,3 +27,6 @@ docs/doxygen/
.vscode/
.DS_Store
Thumbs.db
# AI prompt log (the repository is public)
/docs/ai-prompts/
+123 -1
View File
@@ -1,2 +1,124 @@
# 032-birthday-wisher
# 🚀 Birthday Wisher
Sends a random birthday letter by e-mail to everyone in `birthdays.csv` whose birthday is today. It is the "normal" level of day 32 of Udemy's *100 Days of Code: The Complete Python Pro Bootcamp*, written for course participants and for anyone who browses the repository for ideas.
## 📚 Table of Contents
- [Overview](#-overview)
- [Requirements](#-requirements)
- [Setup](#-setup)
- [Run](#-run)
- [Tests](#-tests)
- [License](#-license)
- [Links](#-links)
- [Appendix: Project documents](#-appendix-project-documents)
## 🧭 Overview
The program reads `birthdays.csv`, compares today's month and day with each row, picks one of `letter_templates/letter_1.txt` to `letter_3.txt` at random, replaces `[NAME]` with the person's name and sends the letter through SMTP with STARTTLS (Gmail by default). It uses only the Python standard library, so it has no runtime dependencies.
![A dry run: the letters that would be sent](docs/images/dry-run.png)
| Path | What it is |
| --- | --- |
| `src/birthday_wisher/` | The program: `domain`, `application`, `infrastructure` and `presentation` layers, constants in `constants.py` |
| `tests/` | pytest tests: `unit`, `integration`, `e2e`; all run offline |
| `birthdays.csv` | The people: `name,email,year,month,day` (dummy data) |
| `letter_templates/` | Three letters with the `[NAME]` placeholder |
| `Doxyfile` | Doxygen configuration; the source carries Doxygen comments |
| `docs/` | Project documents, images and the wiki in English, Danish and Bahasa Malaysia |
## 📋 Requirements
- Python 3.13 or newer, to run the program and the tests.
- A Gmail address and an app password, only to send real e-mail. A dry run and the tests need neither.
- Doxygen, only to build the API documentation (optional).
## 🛠️ Setup
Create and use a local virtual environment, then upgrade pip and install the project with its test tools:
```bash
python -m venv .venv
```
Activate it. On Windows (PowerShell): `.venv\Scripts\Activate.ps1`. On Windows (cmd): `.venv\Scripts\activate`. On Linux and macOS: `source .venv/bin/activate`.
```bash
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
![Creating the .venv](docs/images/venv-setup.png)
To send real e-mail, set two environment variables (see `.env.example`; never commit a real `.env`):
```bash
export GMAIL_ADDRESS="you@gmail.com"
export GMAIL_TOKEN="your-app-password"
```
On Windows PowerShell use `$env:GMAIL_ADDRESS = "you@gmail.com"` and `$env:GMAIL_TOKEN = "your-app-password"`.
## ▶️ Run
Print the letters instead of sending them (pretend today is 17 October 2000):
```bash
python -m birthday_wisher --dry-run --today 2000-10-17
```
Send the letters for today's birthdays:
```bash
python -m birthday_wisher
```
Options: `--dry-run`, `--today YYYY-MM-DD`, `--csv FILE`, `--letters FOLDER`. The program exits with status 1 when setup is wrong or a letter could not be sent. Generate the API documentation with `doxygen Doxyfile` (output in `docs/doxygen/`).
## 🧪 Tests
```bash
python -m pytest
```
The tests use a fake SMTP connection and temporary files. They need no network, no `.env` and no credentials.
![The test run](docs/images/tests.png)
## 📄 License
GNU Affero General Public License v3.0, see [LICENSE](LICENSE).
## 🔗 Links
- [Repository][repository]
- [Documentation][documentation]
- [Issue tracker][issues]
## 📎 Appendix: Project documents
| Document | What it tells you |
| --- | --- |
| [AGENTS.md][agents] | The rules AI agents follow in this repository |
| [Business Case][BC-001] | Why the project exists, its scope and success criteria |
| [Stakeholder Analysis][SA-001] | Who is involved; the stakeholder IDs used for owners and reviewers |
| [Project Plan][PP-001] | The gateways and their schedule |
| [Milestones][milestones] | One document per gateway: Go/No-Go criteria and tasks |
| [Artifact registry][registry] | Where each artifact type lives, the next version, the PO language and domain |
| [Framework README][framework-readme] | The framework this project uses |
| [Framework changelog][framework-changelog] | What changed in each framework release |
---
[repository]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher
[documentation]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/wiki
[issues]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/issues
[agents]: ./AGENTS.md
[BC-001]: ./docs/business-case.md
[SA-001]: ./docs/stakeholder-analysis.md
[PP-001]: ./docs/project-plan.md
[milestones]: ./docs/milestones/
[registry]: ./docs/artifact-registry.md
[framework-readme]: ./framework/README.md
[framework-changelog]: ./framework/CHANGELOG.md
Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

+6 -3
View File
@@ -29,9 +29,9 @@ This plan schedules the three phases that deliver the birthday wisher of [BC-001
| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone |
| --- | --- | --- | --- | --- | --- | --- | --- |
| G1 Project setup | [MIL-001] | 2026-10-17 to 2026-10-18 | 2026-10-18 | S01 | none (plain tasks) | Skeleton, tooling, repository metadata | |
| G2 Core | [MIL-002] | 2026-10-18 to 2026-10-19 | 2026-10-19 | S01 | none (plain tasks) | Working, tested birthday wisher | |
| G3 Documentation | [MIL-003] | 2026-10-19 to 2026-10-20 | 2026-10-20 | S01 | none (plain tasks) | README, tri-lingual wiki, screenshots | |
| G1 Project setup | [MIL-001] | 2026-10-17 to 2026-10-18 | 2026-10-18 | S01 | none (plain tasks) | Skeleton, tooling, repository metadata | [M-188] |
| G2 Core | [MIL-002] | 2026-10-18 to 2026-10-19 | 2026-10-19 | S01 | none (plain tasks) | Working, tested birthday wisher | [M-189] |
| G3 Documentation | [MIL-003] | 2026-10-19 to 2026-10-20 | 2026-10-20 | S01 | none (plain tasks) | README, tri-lingual wiki, screenshots | [M-190] |
```plantuml
@startgantt
@@ -85,3 +85,6 @@ A No-Go at a gate moves every later date by the time needed to fix and re-review
[MIL-002]: ./milestones/mil-002-birthday-wisher-core.md
[MIL-003]: ./milestones/mil-003-documentation-and-publication.md
[052008f]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/commit/052008f21364120a7c4d5ebbff26b8c16e05a21c
[M-188]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/milestones/188
[M-189]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/milestones/189
[M-190]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/milestones/190
+14
View File
@@ -0,0 +1,14 @@
# Arkitektur
🌐 [English](Architecture) · **Dansk** · [Bahasa Melayu](Architecture-ms)
Koden følger en lille clean architecture. Imports peger indad.
| Lag | Mappe | Indeholder |
| --- | --- | --- |
| Domæne | `src/birthday_wisher/domain/` | `Person` og fejlene |
| Applikation | `src/birthday_wisher/application/` | Use casen `send_birthday_wishes` og portene (`BirthdayRepository`, `LetterSource`, `MailSender`) |
| Infrastruktur | `src/birthday_wisher/infrastructure/` | CSV-læser, brevfiler, SMTP-afsender, indstillinger |
| Præsentation | `src/birthday_wisher/presentation/` | Kommandolinjen og composition root |
Testene afspejler lagene: `tests/unit`, `tests/integration`, `tests/e2e`. Kursets hint om en ordbog med `(month, day)` som nøgle er `birthdays_by_day`.
+14
View File
@@ -0,0 +1,14 @@
# Seni Bina
🌐 [English](Architecture) · [Dansk](Architecture-da) · **Bahasa Melayu**
Kod mengikut seni bina bersih yang kecil. Import menuju ke dalam.
| Lapisan | Folder | Mengandungi |
| --- | --- | --- |
| Domain | `src/birthday_wisher/domain/` | `Person` dan ralat |
| Aplikasi | `src/birthday_wisher/application/` | Kes guna `send_birthday_wishes` dan port (`BirthdayRepository`, `LetterSource`, `MailSender`) |
| Infrastruktur | `src/birthday_wisher/infrastructure/` | Pembaca CSV, fail surat, penghantar SMTP, tetapan |
| Pembentangan | `src/birthday_wisher/presentation/` | Baris arahan dan composition root |
Ujian mencerminkan lapisan: `tests/unit`, `tests/integration`, `tests/e2e`. Petunjuk kursus tentang kamus berkunci `(month, day)` ialah `birthdays_by_day`.
+14
View File
@@ -0,0 +1,14 @@
# Architecture
🌐 **English** · [Dansk](Architecture-da) · [Bahasa Melayu](Architecture-ms)
The code follows a small clean architecture. Imports point inward.
| Layer | Folder | Holds |
| --- | --- | --- |
| Domain | `src/birthday_wisher/domain/` | `Person` and the errors |
| Application | `src/birthday_wisher/application/` | The use case `send_birthday_wishes` and the ports (`BirthdayRepository`, `LetterSource`, `MailSender`) |
| Infrastructure | `src/birthday_wisher/infrastructure/` | CSV reader, letter files, SMTP mailer, settings |
| Presentation | `src/birthday_wisher/presentation/` | The command line and the composition root |
The tests mirror the layers: `tests/unit`, `tests/integration`, `tests/e2e`. The course hint of a dictionary keyed by `(month, day)` is `birthdays_by_day`.
+18
View File
@@ -0,0 +1,18 @@
# Konfiguration
🌐 [English](Configuration) · **Dansk** · [Bahasa Melayu](Configuration-ms)
**Personer.** `birthdays.csv` har overskriften `name,email,year,month,day`. Filen i repositoryet indeholder opdigtede data. Erstat den med dine egne, og hold rigtige adresser ude af git.
**Breve.** `letter_templates/letter_1.txt` til `letter_3.txt`. Teksten `[NAME]` erstattes af personens navn. Ét brev vælges tilfældigt.
**Afsender.** To miljøvariabler:
| Variabel | Betydning |
| --- | --- |
| `GMAIL_ADDRESS` | Adressen, e-mailen sendes fra |
| `GMAIL_TOKEN` | Gmail-app-adgangskode |
`.env.example` viser navnene. Læg aldrig en rigtig `.env` i git; den ignoreres af git. Programmet læser kun miljøet og udskriver aldrig tokenet.
**Konstanter.** Server, port, emne og filnavne står i `src/birthday_wisher/constants.py`.
+18
View File
@@ -0,0 +1,18 @@
# Konfigurasi
🌐 [English](Configuration) · [Dansk](Configuration-da) · **Bahasa Melayu**
**Orang.** `birthdays.csv` mempunyai pengepala `name,email,year,month,day`. Fail dalam repositori mengandungi data rekaan. Gantikan dengan data anda sendiri, dan jauhkan alamat sebenar daripada git.
**Surat.** `letter_templates/letter_1.txt` hingga `letter_3.txt`. Teks `[NAME]` diganti dengan nama orang itu. Satu surat dipilih secara rawak.
**Penghantar.** Dua pemboleh ubah persekitaran:
| Pemboleh ubah | Maksud |
| --- | --- |
| `GMAIL_ADDRESS` | Alamat e-mel dihantar daripadanya |
| `GMAIL_TOKEN` | Kata laluan aplikasi Gmail |
`.env.example` menunjukkan namanya. Jangan sekali-kali komit `.env` sebenar; git mengabaikannya. Program hanya membaca persekitaran dan tidak pernah mencetak token.
**Pemalar.** Pelayan, port, subjek dan nama fail ada dalam `src/birthday_wisher/constants.py`.
+18
View File
@@ -0,0 +1,18 @@
# Configuration
🌐 **English** · [Dansk](Configuration-da) · [Bahasa Melayu](Configuration-ms)
**People.** `birthdays.csv` has the header `name,email,year,month,day`. The file in the repository holds dummy data. Replace it with your own, and keep real addresses out of git.
**Letters.** `letter_templates/letter_1.txt` to `letter_3.txt`. The text `[NAME]` is replaced by the person's name. One letter is chosen at random.
**Sender.** Two environment variables:
| Variable | Meaning |
| --- | --- |
| `GMAIL_ADDRESS` | Address the e-mail is sent from |
| `GMAIL_TOKEN` | Gmail app password |
`.env.example` shows the names. Never commit a real `.env`; it is ignored by git. The program reads the environment only and never prints the token.
**Constants.** Server, port, subject and file names are in `src/birthday_wisher/constants.py`.
+17
View File
@@ -0,0 +1,17 @@
# Fødselsdagshilsner
🌐 [English](Home) · **Dansk** · [Bahasa Melayu](Home-ms)
Sender et tilfældigt fødselsdagsbrev på e-mail til alle i `birthdays.csv`, der har fødselsdag i dag. Det er "normal"-niveauet på dag 32 af Udemys *100 Days of Code: The Complete Python Pro Bootcamp*.
![En prøvekørsel](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/dry-run.png)
| Side | Læs den, når du vil |
| --- | --- |
| [Setup](Setup-da) | Oprette et lokalt `.venv` og installere projektet |
| [Usage](Usage-da) | Køre programmet og læse dets output |
| [Configuration](Configuration-da) | Ændre personerne, brevene og afsenderen |
| [Testing](Testing-da) | Køre testene |
| [Architecture](Architecture-da) | Se, hvordan koden er opbygget |
Programmet bruger kun Pythons standardbibliotek: der er ingen runtime-afhængigheder. Kildekode: [repository](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher).
+17
View File
@@ -0,0 +1,17 @@
# Pengucap Hari Lahir
🌐 [English](Home) · [Dansk](Home-da) · **Bahasa Melayu**
Menghantar surat hari jadi rawak melalui e-mel kepada semua orang dalam `birthdays.csv` yang berhari jadi hari ini. Ini ialah tahap "normal" hari ke-32 kursus Udemy *100 Days of Code: The Complete Python Pro Bootcamp*.
![Larian percubaan](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/dry-run.png)
| Halaman | Baca apabila anda ingin |
| --- | --- |
| [Setup](Setup-ms) | Mencipta `.venv` setempat dan memasang projek |
| [Usage](Usage-ms) | Menjalankan program dan membaca outputnya |
| [Configuration](Configuration-ms) | Menukar senarai orang, surat dan penghantar |
| [Testing](Testing-ms) | Menjalankan ujian |
| [Architecture](Architecture-ms) | Melihat bagaimana kod disusun |
Program ini hanya menggunakan pustaka standard Python: tiada kebergantungan masa larian. Kod sumber: [repositori](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher).
+17
View File
@@ -0,0 +1,17 @@
# Birthday Wisher
🌐 **English** · [Dansk](Home-da) · [Bahasa Melayu](Home-ms)
Sends a random birthday letter by e-mail to everyone in `birthdays.csv` whose birthday is today. It is the "normal" level of day 32 of Udemy's *100 Days of Code: The Complete Python Pro Bootcamp*.
![A dry run](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/dry-run.png)
| Page | Read it when you want to |
| --- | --- |
| [Setup](Setup) | Create a local `.venv` and install the project |
| [Usage](Usage) | Run the program and read its output |
| [Configuration](Configuration) | Change the people, the letters and the sender |
| [Testing](Testing) | Run the tests |
| [Architecture](Architecture) | See how the code is organised |
The program uses only the Python standard library: there are no runtime dependencies. Source: [repository](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher).
+20
View File
@@ -0,0 +1,20 @@
# Opsætning
🌐 [English](Setup) · **Dansk** · [Bahasa Melayu](Setup-ms)
Du skal bruge Python 3.13 eller nyere.
```bash
python -m venv .venv
```
Aktivér miljøet. Windows PowerShell: `.venv\Scripts\Activate.ps1`. Windows cmd: `.venv\Scripts\activate`. Linux og macOS: `source .venv/bin/activate`.
```bash
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
![Oprettelse af .venv](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/venv-setup.png)
Tilvalget `dev` installerer pytest, ruff og mypy. Selve programmet kræver intet.
+20
View File
@@ -0,0 +1,20 @@
# Persediaan
🌐 [English](Setup) · [Dansk](Setup-da) · **Bahasa Melayu**
Anda memerlukan Python 3.13 atau lebih baharu.
```bash
python -m venv .venv
```
Aktifkan persekitaran. Windows PowerShell: `.venv\Scripts\Activate.ps1`. Windows cmd: `.venv\Scripts\activate`. Linux dan macOS: `source .venv/bin/activate`.
```bash
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
![Mencipta .venv](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/venv-setup.png)
Tambahan `dev` memasang pytest, ruff dan mypy. Program itu sendiri tidak memerlukan apa-apa.
+20
View File
@@ -0,0 +1,20 @@
# Setup
🌐 **English** · [Dansk](Setup-da) · [Bahasa Melayu](Setup-ms)
You need Python 3.13 or newer.
```bash
python -m venv .venv
```
Activate the environment. Windows PowerShell: `.venv\Scripts\Activate.ps1`. Windows cmd: `.venv\Scripts\activate`. Linux and macOS: `source .venv/bin/activate`.
```bash
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
![Creating the .venv](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/venv-setup.png)
The `dev` extra installs pytest, ruff and mypy. Nothing is needed to run the program itself.
+18
View File
@@ -0,0 +1,18 @@
# Test
🌐 [English](Testing) · **Dansk** · [Bahasa Melayu](Testing-ms)
```bash
python -m pytest
```
![Testkørslen](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/tests.png)
Testene bruger en falsk SMTP-forbindelse og midlertidige filer. De kræver intet netværk, ingen `.env` og ingen adgangskoder. Valgfri kontrol:
```bash
python -m ruff check src tests
python -m mypy src tests
```
API-dokumentation fra Doxygen-kommentarerne: `doxygen Doxyfile` (output i `docs/doxygen/`).
+18
View File
@@ -0,0 +1,18 @@
# Ujian
🌐 [English](Testing) · [Dansk](Testing-da) · **Bahasa Melayu**
```bash
python -m pytest
```
![Larian ujian](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/tests.png)
Ujian menggunakan sambungan SMTP palsu dan fail sementara. Ia tidak memerlukan rangkaian, `.env` atau kelayakan. Semakan pilihan:
```bash
python -m ruff check src tests
python -m mypy src tests
```
Dokumentasi API daripada komen Doxygen: `doxygen Doxyfile` (output dalam `docs/doxygen/`).
+18
View File
@@ -0,0 +1,18 @@
# Testing
🌐 **English** · [Dansk](Testing-da) · [Bahasa Melayu](Testing-ms)
```bash
python -m pytest
```
![The test run](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/tests.png)
The tests use a fake SMTP connection and temporary files. They need no network, no `.env` and no credentials. Optional checks:
```bash
python -m ruff check src tests
python -m mypy src tests
```
API documentation from the Doxygen comments: `doxygen Doxyfile` (output in `docs/doxygen/`).
+26
View File
@@ -0,0 +1,26 @@
# Brug
🌐 [English](Usage) · **Dansk** · [Bahasa Melayu](Usage-ms)
Udskriv brevene i stedet for at sende dem. `--today` lader som om, det er en anden dag:
```bash
python -m birthday_wisher --dry-run --today 2000-10-17
```
![En prøvekørsel](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/dry-run.png)
Send brevene til dagens fødselsdage (kræver [afsenderindstillingerne](Configuration-da)):
```bash
python -m birthday_wisher
```
| Valgmulighed | Betydning |
| --- | --- |
| `--dry-run` | Udskriv e-mailene i stedet for at sende dem |
| `--today YYYY-MM-DD` | Lad som om, det er denne dato |
| `--csv FILE` | Brug en anden fødselsdagsfil |
| `--letters FOLDER` | Brug en anden mappe med brevskabeloner |
Slutstatus 0 betyder succes. Status 1 betyder, at opsætningen er forkert (manglende fil eller indstilling), eller at et brev ikke kunne sendes. En fødselsdag den 29. februar fejres den 28. februar i år, der ikke er skudår.
+26
View File
@@ -0,0 +1,26 @@
# Penggunaan
🌐 [English](Usage) · [Dansk](Usage-da) · **Bahasa Melayu**
Cetak surat tanpa menghantarnya. `--today` berpura-pura hari ini ialah tarikh lain:
```bash
python -m birthday_wisher --dry-run --today 2000-10-17
```
![Larian percubaan](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/dry-run.png)
Hantar surat untuk hari jadi hari ini (memerlukan [tetapan penghantar](Configuration-ms)):
```bash
python -m birthday_wisher
```
| Pilihan | Maksud |
| --- | --- |
| `--dry-run` | Cetak e-mel tanpa menghantarnya |
| `--today YYYY-MM-DD` | Berpura-pura hari ini ialah tarikh ini |
| `--csv FILE` | Guna fail hari jadi lain |
| `--letters FOLDER` | Guna folder templat surat lain |
Status keluar 0 bermaksud berjaya. Status 1 bermaksud persediaan salah (fail atau tetapan tiada) atau satu surat gagal dihantar. Hari jadi pada 29 Februari disambut pada 28 Februari dalam tahun yang bukan tahun lompat.
+26
View File
@@ -0,0 +1,26 @@
# Usage
🌐 **English** · [Dansk](Usage-da) · [Bahasa Melayu](Usage-ms)
Print the letters instead of sending them. `--today` pretends it is another day:
```bash
python -m birthday_wisher --dry-run --today 2000-10-17
```
![A dry run](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/032-birthday-wisher/raw/branch/main/docs/images/dry-run.png)
Send the letters for today's birthdays (needs the [sender settings](Configuration)):
```bash
python -m birthday_wisher
```
| Option | Meaning |
| --- | --- |
| `--dry-run` | Print the e-mails instead of sending them |
| `--today YYYY-MM-DD` | Pretend today is this date |
| `--csv FILE` | Use another birthdays file |
| `--letters FOLDER` | Use another folder of letter templates |
Exit status 0 means success. Status 1 means the setup is wrong (missing file or setting) or a letter could not be sent. A birthday on 29 February is celebrated on 28 February in years that are not leap years.
+14
View File
@@ -0,0 +1,14 @@
**Birthday Wisher**
- [Home](Home)
- [Setup](Setup)
- [Usage](Usage)
- [Configuration](Configuration)
- [Testing](Testing)
- [Architecture](Architecture)
**Languages**
- English: [Home](Home)
- Dansk: [Home](Home-da)
- Bahasa Melayu: [Home](Home-ms)