-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
118 lines (92 loc) · 4.85 KB
/
Copy pathserver.js
File metadata and controls
118 lines (92 loc) · 4.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
const express = require('express');
const axios = require('axios');
const path = require('path');
const fs = require('fs').promises;
const app = express();
const port = 3000;
app.use(express.static(path.join(__dirname, 'public')));
app.get('/api/languages', async (req, res) => {
try {
const data = await fs.readFile('wikipedias.json', 'utf-8');
res.json(JSON.parse(data));
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Failed to fetch languages' });
}
});
app.get('/api/pageviews', async (req, res) => {
try {
const { year, month, lang, limit = 50 } = req.query;
if (!year || !month || !lang) {
return res.status(400).json({ error: 'Year, month, and language are required.' });
}
const projectUrlPart = `${lang}.wikipedia.org`;
const topPagesUrl = `https://wikimedia.org/api/rest_v1/metrics/pageviews/top/${projectUrlPart}/all-access/${year}/${month}/all-days`;
const topPagesResponse = await axios.get(topPagesUrl, { headers: { 'accept': 'application/json' } });
if (!topPagesResponse.data.items || topPagesResponse.data.items.length === 0) {
return res.json([]);
}
const topArticles = topPagesResponse.data.items[0].articles.slice(0, parseInt(limit, 10));
const startOfMonth = `${year}${month.padStart(2, '0')}0100`;
const lastDayOfMonth = new Date(year, month, 0).getDate();
const endOfMonth = `${year}${month.padStart(2, '0')}${lastDayOfMonth}00`;
const detailedDataPromises = topArticles.map(async (article) => {
const articleTitle = encodeURIComponent(article.article.replace(/ /g, '_'));
const baseUrl = `https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/${projectUrlPart}`;
const urls = {
desktop: `${baseUrl}/desktop/all-agents/${articleTitle}/monthly/${startOfMonth}/${endOfMonth}`,
mobileApp: `${baseUrl}/mobile-app/all-agents/${articleTitle}/monthly/${startOfMonth}/${endOfMonth}`,
mobileWeb: `${baseUrl}/mobile-web/all-agents/${articleTitle}/monthly/${startOfMonth}/${endOfMonth}`,
user: `${baseUrl}/all-access/user/${articleTitle}/monthly/${startOfMonth}/${endOfMonth}`,
spider: `${baseUrl}/all-access/spider/${articleTitle}/monthly/${startOfMonth}/${endOfMonth}`,
automated: `${baseUrl}/all-access/automated/${articleTitle}/monthly/${startOfMonth}/${endOfMonth}`
};
const requests = Object.values(urls).map(url =>
axios.get(url, { headers: { 'accept': 'application/json' } }).catch(e => ({ data: { items: [] } }))
);
const responses = await Promise.all(requests);
const extractViews = (response) => {
return response?.data?.items?.[0]?.views || 0;
};
const desktopViews = extractViews(responses[0]);
const mobileAppViews = extractViews(responses[1]);
const mobileWebViews = extractViews(responses[2]);
const allViews = desktopViews + mobileAppViews + mobileWebViews;
const userViews = extractViews(responses[3]);
const spiderViews = extractViews(responses[4]);
const automatedViews = extractViews(responses[5]);
return {
url: `https://${projectUrlPart}/wiki/${article.article.replace(/ /g, '_')}`,
visits: allViews,
returnVisits: 0,
avgDuration: 10,
regions: getRegions(),
devices: getDeviceDistribution(desktopViews, mobileAppViews, mobileWebViews),
agentBreakdown: `user:${userViews};spider:${spiderViews};automated:${automatedViews}`
};
});
const formattedData = await Promise.all(detailedDataPromises);
formattedData.sort((a, b) => b.visits - a.visits);
res.json(formattedData);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Failed to fetch page views' });
}
});
function getRegions() {
return 'global';
}
function getDeviceDistribution(desktopViews, mobileAppViews, mobileWebViews) {
const total = desktopViews + mobileAppViews + mobileWebViews;
if (total === 0) {
return 'desktop:0;mobile-app:0;mobile-web:0';
}
const desktopPercent = Math.round((desktopViews / total) * 100);
const mobileAppPercent = Math.round((mobileAppViews / total) * 100);
// To avoid rounding errors making the sum != 100, the last one can be calculated by subtraction.
const mobileWebPercent = Math.max(0, 100 - desktopPercent - mobileAppPercent);
return `desktop:${desktopPercent};mobile-app:${mobileAppPercent};mobile-web:${mobileWebPercent}`;
}
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});