Skip to content

Commit 4e09832

Browse files
Initial commit: AI Newsletter project
0 parents  commit 4e09832

20 files changed

+1099
-0
lines changed

.env.example

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Mailgun Configuration
2+
MAILGUN_API_KEY=your_mailgun_api_key_here
3+
MAILGUN_DOMAIN=your_mailgun_domain_here
4+
5+
6+
7+
# OpenAI Configuration
8+
OPENAI_API_KEY=your_openai_api_key_here
9+
10+
# Personalization (CSV lists)
11+
PREF_TOPICS=ai,hardware,gaming,geopolitics,macroeconomy
12+
PREF_REGIONS=US,EU,Middle East,Asia
13+
PREF_KEYWORDS=AMD,NVIDIA,Intel,GPU,CPU,SSD
14+
15+
# RSS Feeds (comma-separated)
16+
RSS_FEEDS=https://feeds.bbci.co.uk/news/rss.xml,https://www.reuters.com/rssFeed/worldNews,https://www.theverge.com/rss/index.xml
17+
18+
# Price Watchlist (semicolon-separated entries: 'name|url|currency')
19+
# Example format: Product Name|https://example.com/product|USD
20+
PRICE_WATCH=Example Product|https://example.com/product|USD;Another Item|https://example.com/item|EUR

.github/workflows/build.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: .NET Build and Test
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Setup .NET
17+
uses: actions/setup-dotnet@v4
18+
with:
19+
dotnet-version: '10.0.x'
20+
21+
- name: Restore dependencies
22+
run: dotnet restore
23+
24+
- name: Build
25+
run: dotnet build --no-restore --configuration Release
26+
27+
- name: Test
28+
run: dotnet test --no-build --verbosity normal --configuration Release
29+
30+
# Optional: Publish artifacts
31+
- name: Publish
32+
run: dotnet publish --no-build --configuration Release --output ./publish
33+
34+
- name: Upload artifacts
35+
uses: actions/upload-artifact@v4
36+
with:
37+
name: ai-newsletter
38+
path: ./publish

.gitignore

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# .NET
2+
bin/
3+
obj/
4+
*.user
5+
*.suo
6+
*.cache
7+
*.dll
8+
*.pdb
9+
*.exe
10+
*.log
11+
12+
# Build results
13+
[Dd]ebug/
14+
[Rr]elease/
15+
x64/
16+
x86/
17+
[Aa]rm/
18+
[Aa]rm64/
19+
bld/
20+
[Bb]in/
21+
[Oo]bj/
22+
[Ll]og/
23+
[Ll]ogs/
24+
25+
# Visual Studio
26+
.vs/
27+
*.rsuser
28+
*.suo
29+
*.user
30+
*.userosscache
31+
*.sln.docstates
32+
*.userprefs
33+
34+
# Rider
35+
.idea/
36+
*.sln.iml
37+
38+
# Environment variables - IMPORTANT: Never commit this!
39+
.env
40+
41+
# State files
42+
/data/
43+
state.json
44+
45+
# OS files
46+
.DS_Store
47+
Thumbs.db
48+
desktop.ini
49+
50+
# Rider and VS Code
51+
.vscode/
52+
*.swp
53+
*.swo
54+
*~
55+
56+
# Docker
57+
.dockerignore
58+
docker-compose.override.yml

CONTRIBUTING.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Contributing to AI Newsletter
2+
3+
Thank you for your interest in contributing! Here are some guidelines to help you get started.
4+
5+
## Getting Started
6+
7+
1. Fork the repository
8+
2. Clone your fork: `git clone https://github.com/yourusername/ai-newsletter.git`
9+
3. Create a feature branch: `git checkout -b feature/your-feature-name`
10+
4. Make your changes
11+
5. Test thoroughly
12+
6. Commit with clear messages: `git commit -m "Add feature: description"`
13+
7. Push to your fork: `git push origin feature/your-feature-name`
14+
8. Open a Pull Request
15+
16+
## Development Setup
17+
18+
1. Install .NET 10 SDK
19+
2. Copy `.env.example` to `.env` and configure with test credentials
20+
3. Run `dotnet restore` to install dependencies
21+
4. Run `dotnet build` to verify everything compiles
22+
5. Run `dotnet run` to test locally
23+
24+
## Code Style
25+
26+
- Follow standard C# conventions
27+
- Use meaningful variable names
28+
- Add comments for complex logic
29+
- Keep methods focused and concise
30+
- Use async/await for I/O operations
31+
32+
## Testing
33+
34+
- Test your changes thoroughly before submitting
35+
- Ensure the build passes: `dotnet build`
36+
- Verify no secrets are committed
37+
38+
## Pull Request Guidelines
39+
40+
- Keep PRs focused on a single feature or fix
41+
- Update README.md if adding new features
42+
- Describe your changes clearly in the PR description
43+
- Link any related issues
44+
45+
## Reporting Issues
46+
47+
- Use GitHub Issues
48+
- Provide clear reproduction steps
49+
- Include error messages and logs (sanitize any secrets!)
50+
- Specify your environment (.NET version, OS, etc.)
51+
52+
## Feature Requests
53+
54+
We welcome feature requests! Please:
55+
- Check if it's already been requested
56+
- Describe the use case clearly
57+
- Explain why it would benefit users
58+
59+
## Questions?
60+
61+
Feel free to open a discussion or issue if you have questions!
62+
63+
Thank you for contributing! ??

DigestComposer.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// DigestComposer.cs
2+
using System.Text;
3+
4+
public static class DigestComposer
5+
{
6+
public static string BuildMarkdown(
7+
List<TopicTrend> developing,
8+
List<NewsItem> relevant,
9+
List<PriceItem> prices)
10+
{
11+
var sb = new StringBuilder();
12+
var now = DateTimeOffset.UtcNow.ToString("u");
13+
14+
sb.AppendLine($"# 3-Day Digest — " + now);
15+
sb.AppendLine();
16+
17+
// Developing stories
18+
sb.AppendLine("## Developing stories (what changed)");
19+
foreach (var t in developing.Take(6))
20+
sb.AppendLine($"- **{t.Topic}** — now: {t.CountNow}, prev: {t.CountPrev}, Δ: {t.Slope:+#;-#;0}");
21+
22+
sb.AppendLine();
23+
sb.AppendLine("## Worldwide but relevant to you");
24+
foreach (var n in relevant.Take(8))
25+
sb.AppendLine($"- [{n.Title}]({n.Link}) — {n.Source} ({n.Published:yyyy-MM-dd})");
26+
27+
sb.AppendLine();
28+
sb.AppendLine("## Price trends (watchlist)");
29+
foreach (var p in prices)
30+
{
31+
var (decision, why) = PriceTracker.BuyHold(p);
32+
var last = p.Series.OrderByDescending(x => x.Ts).FirstOrDefault();
33+
sb.AppendLine($"- **{p.Name}** — {decision}. {why}. Latest: {(last is null ? "n/a" : $"{last.Price} {p.Currency} on {last.Ts:yyyy-MM-dd}")}");
34+
}
35+
36+
// metadata footer
37+
var footer = new
38+
{
39+
version = "v0.2",
40+
digest_id = DateTimeOffset.UtcNow.ToString("yyyy-MM-ddTHH-mm-ssZ"),
41+
items_considered = relevant.Count,
42+
price_items = prices.Select(p => new {
43+
p.Name,
44+
p.Url,
45+
last = p.Series.OrderByDescending(x => x.Ts).FirstOrDefault()?.Price
46+
})
47+
};
48+
sb.AppendLine();
49+
sb.AppendLine("```json");
50+
sb.AppendLine(System.Text.Json.JsonSerializer.Serialize(footer));
51+
sb.AppendLine("```");
52+
53+
return sb.ToString();
54+
}
55+
}

Dockerfile

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
2+
3+
# This stage is used when running from VS in fast mode (Default for Debug configuration)
4+
FROM mcr.microsoft.com/dotnet/runtime:10.0 AS base
5+
USER $APP_UID
6+
WORKDIR /app
7+
8+
9+
# This stage is used to build the service project
10+
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
11+
ARG BUILD_CONFIGURATION=Release
12+
WORKDIR /src
13+
COPY ["ai-newsletter.csproj", "."]
14+
RUN dotnet restore "./ai-newsletter.csproj"
15+
COPY . .
16+
WORKDIR "/src/."
17+
RUN dotnet build "./ai-newsletter.csproj" -c $BUILD_CONFIGURATION -o /app/build
18+
19+
# This stage is used to publish the service project to be copied to the final stage
20+
FROM build AS publish
21+
ARG BUILD_CONFIGURATION=Release
22+
RUN dotnet publish "./ai-newsletter.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
23+
24+
# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration)
25+
FROM base AS final
26+
WORKDIR /app
27+
COPY --from=publish /app/publish .
28+
ENTRYPOINT ["dotnet", "ai-newsletter.dll"]

0 commit comments

Comments
 (0)