Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .dagger/prompts/assignment.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ You are a programmer working on the Greetings API project
2. Evaluate the architecture of the project at `## Project Architecture` in CONTRIBUTING.md to think about what files may be relevant to the solution
3. Understand how the assignment should be implemented in the codebase
4. Implement the assignment in the workspace provided
5. Run the checks to make sure the changes are valid and incorporate any changes needed to pass checks
5. **CRITICAL**: Update documentation in `docs/index.mdx` to reflect any new functionality, endpoints, or changes
6. Run the checks to make sure the changes are valid and incorporate any changes needed to pass checks

## Assignment

Expand All @@ -17,4 +18,5 @@ Here is your assignment: $assignment
- The workspace has tools to let you read and write the code as well as run the tests
- Be sure to always write your changes to the workspace
- Always run check after writing changes to the workspace
- **IMPORTANT**: Changes to project functionality MUST be reflected in changes to the documentation (`docs/index.mdx`)
- You are not done until the check tool is successful and the assignment is complete
28 changes: 20 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,12 @@ greetings-api/

- **Language**: Go
- **Framework**: Gorilla Mux for routing, CORS middleware
- **Structure**: Simple REST API with two endpoints:
- **Structure**: Simple REST API with endpoints for greetings and farewells:
- `GET /` - Returns a random greeting
- `GET /{language}` - Returns a greeting in the specified language
- **Data**: Greetings are stored in `greetings.json` and embedded in the binary
- `GET /farewell` - Returns a random farewell
- `GET /farewell/{language}` - Returns a farewell in the specified language
- **Data**: Greetings are stored in `greetings.json` and farewells in `farewells.json`, both embedded in the binary
- **Testing**: Uses `gotest.tools` for unit tests

### Frontend Architecture
Expand Down Expand Up @@ -154,10 +156,17 @@ npm run lint
- **TypeScript**: Follow the ESLint configuration in the project
- **Commits**: Use clear, descriptive commit messages

### Documentation
### Documentation Requirements

**⚠️ CRITICAL**: Changes to project functionality MUST be reflected in documentation updates.

- **Developer Docs**: Update CONTRIBUTING.md with any architectural changes
- **Product Docs**: Update docs/ with relevant product changes
- **Product Docs**: Update `docs/index.mdx` with any new endpoints, functionality, or changes that affect users
- **API Documentation**: When adding new endpoints, ensure they are properly documented with:
- Endpoint paths and HTTP methods
- Example requests and responses
- Updated supported languages table if applicable
- Error handling examples

### Testing Requirements

Expand All @@ -174,22 +183,25 @@ npm run lint

2. **Make your changes** following the code style guidelines

3. **Test your changes** thoroughly:
3. **Update documentation** as required (see Documentation Requirements above)

4. **Test your changes** thoroughly:
```bash
dagger call check
```

4. **Commit your changes** with clear commit messages
5. **Commit your changes** with clear commit messages

5. **Push to your fork**:
6. **Push to your fork**:
```bash
git push origin feature/your-feature-name
```

6. **Create a Pull Request** on GitHub with:
7. **Create a Pull Request** on GitHub with:
- Clear description of changes
- Reference to any related issues
- Screenshots if UI changes are involved
- Confirmation that documentation has been updated if functionality changed

## Getting Help

Expand Down
89 changes: 65 additions & 24 deletions docs/index.mdx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Greetings API Documentation

Welcome to the Greetings API! This simple service allows you to retrieve greetings in various languages.
Welcome to the Greetings API! This simple service allows you to retrieve greetings and farewells in various languages.

## Using the REST API

The Greetings API provides two main endpoints for retrieving greetings:
The Greetings API provides endpoints for retrieving both greetings and farewells:

### Get a Random Greeting

Expand Down Expand Up @@ -39,38 +39,72 @@ GET http://locahost:8080/french
}
```

### Get a Random Farewell

```
GET http://locahost:8080/farewell
```

**Example Response:**
```json
{
"farewell": "Goodbye, World!"
}
```

### Get a Farewell in a Specific Language

```
GET http://locahost:8080/farewell/{language}
```

Replace `{language}` with one of the supported language codes.

**Example Request:**
```
GET http://locahost:8080/farewell/french
```

**Example Response:**
```json
{
"farewell": "Au revoir, Monde !"
}
```

## Supported Languages

The API currently supports the following languages:

| Language Code | Greeting |
|---------------|----------|
| english | Hello, World! |
| british | Hello, World! Cheers! |
| french | Bonjour, Monde ! |
| italian | Ciao, Mondo! |
| spanish | ¡Hola, Mundo! |
| german | Hallo, Welt! |
| mandarin | 你好,世界! |
| hindi | नमस्ते दुनिया! |
| arabic | مرحبا بالعالم! |
| bengali | ওহে বিশ্ব! |
| russian | Привет, мир! |
| portuguese | Olá, Mundo! |
| urdu | ہیلو، دنیا! |
| indonesian | Halo Dunia! |
| japanese | こんにちは世界! |
| marathi | नमस्कार जग! |
| telugu | హలో ప్రపంచం! |
| Language Code | Greeting | Farewell |
|---------------|----------|----------|
| english | Hello, World! | Goodbye, World! |
| british | Hello, World! Cheers! | Goodbye, World! Cheerio! |
| french | Bonjour, Monde ! | Au revoir, Monde ! |
| italian | Ciao, Mondo! | Arrivederci, Mondo! |
| spanish | ¡Hola, Mundo! | ¡Adiós, Mundo! |
| german | Hallo, Welt! | Auf Wiedersehen, Welt! |
| mandarin | 你好,世界! | 再见,世界! |
| hindi | नमस्ते दुनिया! | अलविदा दुनिया! |
| arabic | مرحبا بالعالم! | وداعا يا عالم! |
| bengali | ওহে বিশ্ব! | বিদায় পৃথিবী! |
| russian | Привет, мир! | До свидания, мир! |
| portuguese | Olá, Mundo! | Adeus, Mundo! |
| urdu | ہیلو، دنیا! | الوداع، دنیا! |
| indonesian | Halo Dunia! | Selamat tinggal Dunia! |
| japanese | こんにちは世界! | さようなら世界! |
| marathi | नमस्कार जग! | निरोप जग! |
| telugu | హలో ప్రపంచం! | వీడ్కోలు ప్రపంచం! |

## Using the Greetings Website

If you prefer a web interface, you can visit the website at http://locahost:8081/ where you can:

1. View random greetings with a simple click
2. Experience our user-friendly interface
2. View random farewells with a simple click
3. Experience our user-friendly interface

Simply click the greeting button (👋) to get a new random greeting displayed on the screen.
Simply click the greeting button (👋) to get a new random greeting or the farewell button (👋😢) to get a new random farewell displayed on the screen.

## API Limits

Expand All @@ -80,13 +114,20 @@ Currently, there are no rate limits on the API usage, but please be respectful o

If you request a language that doesn't exist, the API will return an appropriate error message with a 400 status code.

Example error response:
Example error response for greeting:
```json
{
"error": "no greeting found for language 'klingon'"
}
```

Example error response for farewell:
```json
{
"error": "no farewell found for language 'klingon'"
}
```

## Need Help?

If you have any questions or need assistance with the Greetings API, please open an issue on our GitHub repository.
19 changes: 19 additions & 0 deletions farewells.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[
{ "language": "english", "farewell": "Goodbye, World!" },
{ "language": "british", "farewell": "Goodbye, World! Cheerio!" },
{ "language": "french", "farewell": "Au revoir, Monde !" },
{ "language": "italian", "farewell": "Arrivederci, Mondo!" },
{ "language": "spanish", "farewell": "¡Adiós, Mundo!" },
{ "language": "german", "farewell": "Auf Wiedersehen, Welt!" },
{ "language": "mandarin", "farewell": "再见,世界!" },
{ "language": "hindi", "farewell": "अलविदा दुनिया!" },
{ "language": "arabic", "farewell": "وداعا يا عالم!" },
{ "language": "bengali", "farewell": "বিদায় পৃথিবী!" },
{ "language": "russian", "farewell": "До свидания, мир!" },
{ "language": "portuguese", "farewell": "Adeus, Mundo!" },
{ "language": "urdu", "farewell": "الوداع، دنیا!" },
{ "language": "indonesian", "farewell": "Selamat tinggal Dunia!" },
{ "language": "japanese", "farewell": "さようなら世界!" },
{ "language": "marathi", "farewell": "निरोप जग!" },
{ "language": "telugu", "farewell": "వీడ్కోలు ప్రపంచం!" }
]
68 changes: 68 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,34 @@ import (
//go:embed greetings.json
var greetingsJson []byte

//go:embed farewells.json
var farewellsJson []byte

type Greeting struct {
Language string `json:"language"`
Greeting string `json:"greeting"`
}

type Farewell struct {
Language string `json:"language"`
Farewell string `json:"farewell"`
}

func main() {
var greetings []*Greeting
err := json.Unmarshal(greetingsJson, &greetings)
if err != nil {
fmt.Printf("error loading greetings: %s\n", err)
os.Exit(1)
}

var farewells []*Farewell
err = json.Unmarshal(farewellsJson, &farewells)
if err != nil {
fmt.Printf("error loading farewells: %s\n", err)
os.Exit(1)
}

router := mux.NewRouter()

router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -57,6 +73,34 @@ func main() {
}
}).Methods("GET")

// Farewell endpoints
router.HandleFunc("/farewell", func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("got /farewell request from %s\n", r.RemoteAddr)
w.Header().Set("Content-Type", "application/json")
farewell, err := SelectFarewell(farewells, "random")
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
Copy link

Copilot AI Jul 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing return statement after http.Error call. The function continues execution and attempts to write response even after an error, which could cause issues.

Suggested change
http.Error(w, err.Error(), http.StatusBadRequest)
http.Error(w, err.Error(), http.StatusBadRequest)
return

Copilot uses AI. Check for mistakes.
}
_, err = w.Write([]byte(FormatFarewellResponse(farewell)))
if err != nil {
panic(err)
}
}).Methods("GET")

router.HandleFunc("/farewell/{language}", func(w http.ResponseWriter, r *http.Request) {
language := mux.Vars(r)["language"]
fmt.Printf("got /farewell/{language} request from %s\n", r.RemoteAddr)
w.Header().Set("Content-Type", "application/json")
farewell, err := SelectFarewell(farewells, language)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
Copy link

Copilot AI Jul 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing return statement after http.Error call. The function continues execution and attempts to write response even after an error, which could cause issues.

Suggested change
http.Error(w, err.Error(), http.StatusBadRequest)
http.Error(w, err.Error(), http.StatusBadRequest)
return

Copilot uses AI. Check for mistakes.
}
_, err = w.Write([]byte(FormatFarewellResponse(farewell)))
if err != nil {
panic(err)
}
}).Methods("GET")

c := cors.New(cors.Options{
AllowedOrigins: []string{
"http://greetings.kylepenfound.com",
Expand All @@ -78,6 +122,10 @@ func FormatResponse(greeting *Greeting) string {
return fmt.Sprintf("{\"greeting\":\"%s\"}", greeting.Greeting)
}

func FormatFarewellResponse(farewell *Farewell) string {
return fmt.Sprintf("{\"farewell\":\"%s\"}", farewell.Farewell)
}

func SelectGreeting(greetings []*Greeting, language string) (*Greeting, error) {
if len(greetings) == 0 {
return nil, errors.New("no greetings available")
Expand All @@ -97,3 +145,23 @@ func SelectGreeting(greetings []*Greeting, language string) (*Greeting, error) {

return nil, fmt.Errorf("no greeting found for language '%s'", language)
}

func SelectFarewell(farewells []*Farewell, language string) (*Farewell, error) {
if len(farewells) == 0 {
return nil, errors.New("no farewells available")
}

if language == "random" {
// Get random item from farewells slice
randomIndex := rand.Intn(len(farewells))
return farewells[randomIndex], nil
}

for _, farewell := range farewells {
if farewell.Language == language {
return farewell, nil
}
}

return nil, fmt.Errorf("no farewell found for language '%s'", language)
}
41 changes: 41 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,37 @@ func TestSelectGreeting(t *testing.T) {
assert.Error(t, err, "no greeting found for language ''")
}

func TestSelectFarewell(t *testing.T) {
var farewells []*Farewell
err := json.Unmarshal(farewellsJson, &farewells)
if err != nil {
fmt.Printf("error loading farewells: %s\n", err)
os.Exit(1)
}

english := &Farewell{
Farewell: "Goodbye, World!",
Language: "english",
}

// Test with a language
f, err := SelectFarewell(farewells, "english")
assert.NilError(t, err)
assert.Equal(t, *english, *f)

// Test random
_, err = SelectFarewell(farewells, "random")
assert.NilError(t, err)

// Test invalid language
_, err = SelectFarewell(farewells, "foooooo")
assert.Error(t, err, "no farewell found for language 'foooooo'")

// Test empty language
_, err = SelectFarewell(farewells, "")
assert.Error(t, err, "no farewell found for language ''")
}

func TestFormatResponse(t *testing.T) {
g := &Greeting{
Greeting: "Hello, World!",
Expand All @@ -49,3 +80,13 @@ func TestFormatResponse(t *testing.T) {
formatted := FormatResponse(g)
assert.Equal(t, "{\"greeting\":\"Hello, World!\"}", formatted)
}

func TestFormatFarewellResponse(t *testing.T) {
f := &Farewell{
Farewell: "Goodbye, World!",
Language: "english",
}

formatted := FormatFarewellResponse(f)
assert.Equal(t, "{\"farewell\":\"Goodbye, World!\"}", formatted)
}
Loading