Skip to content

Commit dc0b3af

Browse files
authored
Merge pull request #875 from Thakar-Advait/main
added: Backend for IndustryTrends Feature
2 parents 1bdcf64 + ed4c1bc commit dc0b3af

25 files changed

+3229
-0
lines changed

backend/.env.sample

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
PORT = "your_server_port"
2+
MONGO_URI = "your_mongo_uri"
3+
DB_NAME = "your_db_name"

backend/.gitignore

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
bin
2+
obj
3+
csx
4+
.vs
5+
edge
6+
Publish
7+
8+
*.user
9+
*.suo
10+
*.cscfg
11+
*.Cache
12+
project-lock.json
13+
14+
15+
/packages
16+
/TestResults
17+
18+
/tools/NuGet.exe
19+
/App_Data
20+
/secrets
21+
/data
22+
.secrets
23+
appsettings.json
24+
local.settings.json
25+
26+
node_modules
27+
dist
28+
29+
# Local python packages
30+
.python_packages/
31+
32+
# Python Environments
33+
.env
34+
.venv
35+
env/
36+
venv/
37+
ENV/
38+
env.bak/
39+
venv.bak/
40+
41+
# Byte-compiled / optimized / DLL files
42+
__pycache__/
43+
*.py[cod]
44+
*$py.class
45+
46+
# Azurite artifacts
47+
__blobstorage__
48+
__queuestorage__
49+
__azurite_db*__.json
50+
51+
.vscode
52+
53+
test
54+

backend/README.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
2+
# 🚀 DevDisplay API: Your Gateway to Developer Trends
3+
4+
## 🌟 Project Overview
5+
6+
DevDisplay API is a powerful backend service that aggregates and serves trending developer content from GitHub and Dev.to. It provides developers and tech enthusiasts with scraped insights into the most exciting developments in the tech world.
7+
8+
## ✨ Key Features
9+
10+
- **Trending Insights**: Discover top developers, repositories, and posts
11+
- **Regularly scraped data**: Latest data scraped from authentic sources
12+
- **Flexible Time Frames**: Choose from daily, weekly, or monthly trending data
13+
- **Multi-Source Aggregation**: Pulls data from GitHub and Dev.to
14+
- **Newsletter Subscription**: Stay updated with the latest tech trends
15+
16+
## 🛠 Tech Stack
17+
18+
- **Backend**: Node.js & Express.js
19+
- **Database**: MongoDB with Mongoose ORM
20+
- **Data Sources**: GitHub.com, Dev.to
21+
22+
## 📂 Project Structure
23+
24+
```
25+
DevDisplay-API/
26+
27+
├── controllers/
28+
│ ├── dev.controllers.js
29+
│ ├── github.controllers.js
30+
│ └── subscribers.controllers.js
31+
32+
├── db/
33+
│ └── index.js
34+
|
35+
├── cron/
36+
│ └── dev.cron.js
37+
│ └── github.cron.js
38+
│ └── test.cron.js
39+
40+
├── models/
41+
│ ├── developers.models.js
42+
│ ├── post.models.js
43+
│ ├── repositories.models.js
44+
│ └── subscribers.models.js
45+
46+
├── routes/
47+
│ ├── dev.routes.js
48+
│ ├── github.routes.js
49+
│ └── subscribers.routes.js
50+
51+
└── utils/
52+
├── randomPeriod.utils.js
53+
├── response.utils.js
54+
└── urlBuilder.utils.js
55+
56+
```
57+
58+
## 🌐 API Endpoints
59+
60+
### Dev.to Endpoints
61+
62+
- `GET /devdisplay/v1/trending/dev/posts/:since`
63+
- `GET /devdisplay/v1/trending/dev/getRandomPost`
64+
65+
### GitHub Endpoints
66+
67+
- `GET /devdisplay/v1/trending/github/repositories/:since`
68+
- `GET /devdisplay/v1/trending/github/developers/:since`
69+
- `GET /devdisplay/v1/trending/github/getRandomDev`
70+
- `GET /devdisplay/v1/trending/github/getRandomRepo`
71+
72+
### Subscription Endpoints
73+
74+
- `POST /devdisplay/v1/subscribers`
75+
76+
## 🚀 Quick Start Guide
77+
78+
### Prerequisites
79+
80+
- Node.js
81+
- npm
82+
- MongoDB
83+
84+
### Installation Steps
85+
86+
1. Clone the repository
87+
88+
```bash
89+
git clone https://github.com/Thakar-Advait/DevDisplay-API.git
90+
cd DevDisplay-API
91+
92+
```
93+
94+
2. Install Dependencies
95+
96+
```bash
97+
npm install
98+
99+
```
100+
101+
3. Configure Environment Variables Create a `.env` file with the following variables:
102+
103+
```
104+
PORT=3000
105+
MONGO_URI=your_mongodb_connection_string
106+
DB_NAME=devdisplay
107+
108+
```
109+
110+
4. Prepare MongoDB Collections Ensure your MongoDB database has these collections:
111+
112+
- `daily_trending_devs`
113+
- `daily_trending_posts`
114+
- `daily_trending_repos`
115+
- `weekly_trending_devs`
116+
- `weekly_trending_posts`
117+
- `weekly_trending_repos`
118+
- `monthly_trending_devs`
119+
- `monthly_trending_posts`
120+
- `monthly_trending_repos`
121+
- `tests`
122+
5. Start the Server
123+
124+
```bash
125+
npm run dev
126+
127+
```
128+
129+
## 🔒 Environment Configuration
130+
131+
Refer to `.env.sample` for detailed environment variable setup.
132+
133+
## 📄 License
134+
135+
[Insert Your License Here]
136+
137+
## 🙌 Acknowledgments
138+
139+
Special thanks to GitHub and Dev.to for providing the incredible developer data that powers this API.
140+
141+
----------
142+
143+
**Built with ❤️ by Developers, for Developers**

backend/app.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import express from "express";
2+
import { devRouter } from "./routes/dev.routes.js";
3+
import { githubRouter } from "./routes/github.routes.js";
4+
import { subscribersRouter } from "./routes/subscribers.routes.js";
5+
import { getSubscribers } from "./controllers/subscribers.controllers.js";
6+
import Subscribers from "./models/subscribers.models.js";
7+
const app = express();
8+
9+
// Middleware to parse incoming JSON requests
10+
app.use(express.json());
11+
12+
// Use the devRouter for the "/api/v1/trending/dev" route
13+
app.use("/devdisplay/v1/trending/dev", devRouter);
14+
15+
// Use the githubRouter for the "/api/v1/trending/github" route
16+
app.use("/devdisplay/v1/trending/github", githubRouter);
17+
18+
app.use("/devdisplay/v1/subscribers", getSubscribers);
19+
20+
app.get("/", (req, res) => {
21+
res.status(200).json({
22+
message: "Welcome to the DevDisplay API!"
23+
});
24+
})
25+
26+
app.get("/health", (req, res) => {
27+
res.status(200).json({
28+
message: "DevDisplay API is healthy!"
29+
});
30+
})
31+
32+
// Global error handling middleware (optional)
33+
app.use((err, req, res, next) => {
34+
console.error(err.stack); // Log the error stack for debugging
35+
res.status(500).json({
36+
message: "Something went wrong!",
37+
error: err.message
38+
});
39+
});
40+
41+
export default app;
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import * as Dev_models from "../models/post.models.js";
2+
import * as responseClass from "../utils/response.utils.js";
3+
import { pickRandomPeriod } from "../utils/randomPeriod.utils.js"
4+
5+
// Helper function to fetch posts based on time period
6+
const fetchPostsForPeriod = async (timePeriod) => {
7+
let model;
8+
switch (timePeriod) {
9+
case "daily":
10+
model = Dev_models.Post_daily;
11+
break;
12+
case "weekly":
13+
model = Dev_models.Post_weekly;
14+
break;
15+
case "monthly":
16+
model = Dev_models.Post_monthly;
17+
break;
18+
default:
19+
throw new responseClass.ApiError(400, "Invalid time period specified.");
20+
}
21+
22+
// Fetching posts for the chosen period
23+
const response = await model.find();
24+
if (!response || response.length === 0) {
25+
throw new responseClass.ApiError(404, `No trending posts found for time period: '${timePeriod}'`);
26+
}
27+
return response;
28+
};
29+
30+
const fetchTrendingPosts = async (req, res) => {
31+
// Extract the "since" parameter from the URL, defaulting to "daily" if not provided
32+
const { since = 'daily' } = req.params;
33+
34+
try {
35+
// Fetch posts based on the time period
36+
const posts = await fetchPostsForPeriod(since);
37+
38+
// Return a consistent response with the fetched posts
39+
return res.status(200).json(new responseClass.ApiResponse(
40+
200,
41+
`Fetched trending posts for time period: '${since}'`,
42+
posts
43+
));
44+
45+
} catch (error) {
46+
// Generic error handling for unexpected errors
47+
console.error(error); // Optional: Add logging to track errors
48+
return res.status(500).json(new responseClass.ApiResponse(
49+
500,
50+
`Something went wrong while fetching trending posts for time period: '${since}' --> \n${error.message || error}`
51+
));
52+
}
53+
}
54+
55+
const fetchRandomPost = async (req, res) => {
56+
const since = pickRandomPeriod();
57+
try {
58+
let posts;
59+
switch (since) {
60+
case "daily":
61+
posts = await Dev_models.Post_daily.aggregate([
62+
{ $sample: { size: 1 } }
63+
])
64+
break;
65+
case "weekly":
66+
posts = await Dev_models.Post_weekly.aggregate([
67+
{ $sample: { size: 1 } }
68+
])
69+
break;
70+
case "monthly":
71+
posts = await Dev_models.Post_monthly.aggregate([
72+
{ $sample: { size: 1 } }
73+
])
74+
break;
75+
default:
76+
posts = await Dev_models.Post_daily.aggregate([
77+
{ $sample: { size: 1 } }
78+
])
79+
break;
80+
}
81+
if (posts.length > 0) {
82+
console.log('Random Document:', posts[0]);
83+
return res.status(200).json(new responseClass.ApiResponse(200, `Fetched random post for time period: '${since}'`, posts[0]));
84+
} else {
85+
console.log('No documents found.');
86+
return res.status(404).json(new responseClass.ApiResponse(404, `No random posts found for time period: '${since}'`));
87+
}
88+
} catch (error) {
89+
console.error(error);
90+
return res.status(500).json(new responseClass.ApiResponse(500, `Something went wrong while fetching random post for time period: '${since}' --> \n${error.message || error}`));
91+
}
92+
}
93+
94+
export {
95+
fetchTrendingPosts,
96+
fetchRandomPost
97+
};

0 commit comments

Comments
 (0)