-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
924 changed files
with
158,162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: umami-report | ||
|
||
on: | ||
schedule: | ||
- cron: '0 10 * * *' | ||
# Allows you to run this workflow manually from the Actions tab | ||
workflow_dispatch: | ||
|
||
jobs: | ||
umamiReport: | ||
name: umami report example | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Create Umami report | ||
uses: boly38/action-umami-report@v1 | ||
with: | ||
umami-server: ${{secrets.UMAMI_SERVER}} | ||
umami-user: ${{secrets.UMAMI_USERNAME}} | ||
umami-password: ${{secrets.UMAMI_PASSWORD}} | ||
umami-site-domain: ${{secrets.UMAMI_SIDE_DOMAIN}} | ||
|
||
- name: Send Umami report to discord channel | ||
uses: sinshutu/upload-to-discord@master | ||
env: | ||
DISCORD_WEBHOOK: ${{ secrets.UMAMI_TO_DISCORD_WEBHOOK }} | ||
with: | ||
args: umamiReport.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#Intellij | ||
.idea/ | ||
*.iml | ||
|
||
# github actions require node_modules too | ||
# https://docs.github.com/en/actions/creating-actions/creating-a-javascript-action | ||
|
||
# dont push | ||
*.dontpush.* | ||
umamiReport.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,49 @@ | ||
# action-umami-report | ||
|
||
This action prints daily umami report into a given file | ||
|
||
## Inputs | ||
|
||
## `umami-server` | ||
|
||
**Required** The umami server instance. Example `"https://umami.mysite.com"`. | ||
|
||
## `umami-user` | ||
|
||
**Required** The umami server instance user. Default `"admin"`. | ||
|
||
## `umami-password` | ||
|
||
**Required** The umami server instance password. | ||
|
||
## `umami-site-domain` | ||
|
||
**Required** The umami site domain name. Example `"www.mysite.com"`.Default selecting the first site domain name. | ||
|
||
## Outputs | ||
|
||
## `umamiReport.md` | ||
|
||
The umami report for last 24h. | ||
|
||
## Example usage | ||
|
||
```yaml | ||
- name: Create Umami report | ||
uses: boly38/action-umami-report@v1 | ||
with: | ||
umami-server: ${{secrets.UMAMI_SERVER}} | ||
umami-user: ${{secrets.UMAMI_USERNAME}} | ||
umami-password: ${{secrets.UMAMI_PASSWORD}} | ||
umami-site-domain: ${{secrets.UMAMI_SIDE_DOMAIN}} | ||
``` | ||
Full working sample: cf. [umamiReport.yml](.github/workflows/umamiReport.yml) | ||
# See also | ||
## Umami | ||
- Umami [API](https://umami.is/docs/api) - [Source](https://github.com/umami-software/umami) | ||
## possible next step | ||
- send the report [by email](https://github.com/dawidd6/action-send-mail), on [discord](https://github.com/marketplace/actions/upload-to-discord), etc.. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
name: Create Umami report | ||
description: Produce umamiReport.md from umami site last 24h stats | ||
author: boly38 | ||
inputs: | ||
umami-server: | ||
description: The umami server instance. | ||
required: true | ||
umami-user: | ||
description: The umami server instance user | ||
required: true | ||
umami-password: | ||
description: The umami server instance password | ||
required: true | ||
umami-site-domain: | ||
description: The umami site domain name | ||
required: false | ||
runs: | ||
using: node16 | ||
main: main.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#!/bin/bash | ||
export UMAMI_SERVER="https://umami.replace-me.exemple.com" | ||
export UMAMI_USER="admin" | ||
export UMAMI_PASSWORD="12333321" | ||
# export UMAMI_SITE_DOMAIN="replace-me.exemple.com" | ||
export UMAMI_SITE_DOMAIN="*first*" | ||
|
||
### Dev debug API | ||
# export UMAMI_DEBUG_RESPONSE=true | ||
# export UMAMI_DEBUG_REQUEST=true | ||
### Dev debug Action | ||
# export UMAMI_DEBUG_ACTION=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import fs from 'fs'; | ||
import dayjs from 'dayjs'; | ||
|
||
import umamiApi from './umami/api.js' | ||
|
||
const DEBUG_ACTION = process.env.UMAMI_DEBUG_ACTION === 'true'; | ||
const rethrow = (err) => {throw err;} | ||
|
||
class Action { | ||
|
||
static async produceReport(umamiSite, umamiSiteStat, targetFile) { | ||
const reportDateTime = dayjs().format('DD/MM/YYYY HH:mm'); | ||
var umamiReport = `# ${reportDateTime} - Umami report\n` | ||
umamiReport += `for ${umamiSite.domain} [last 24 hours] :\n\n`; | ||
umamiReport += ` - ${umamiSiteStat.pageviews.value} (change:${umamiSiteStat.pageviews.change}) page views\n`; | ||
umamiReport += ` - ${umamiSiteStat.uniques.value} (change:${umamiSiteStat.uniques.change}) uniques\n`; | ||
umamiReport += ` - ${umamiSiteStat.bounces.value} (change:${umamiSiteStat.bounces.change}) bounces\n`; | ||
umamiReport += ` - ${umamiSiteStat.totaltime.value} (change:${umamiSiteStat.totaltime.change}) totaltime\n`; | ||
umamiReport += '\n'; | ||
fs.writeFileSync(targetFile, umamiReport); | ||
} | ||
|
||
static async umamiDailyReportV0(server, user, password, domain = '*first*', targetFile = 'umamiReport.md') { | ||
const authData = await umamiApi.login(server, user, password).catch(rethrow); | ||
const sites = await umamiApi.getSites(server, authData).catch(rethrow); | ||
const site = umamiApi.selectSiteByDomain(sites, domain); | ||
const siteStats = await umamiApi.getStats(server, authData, site).catch(rethrow); | ||
DEBUG_ACTION && console.log(site); | ||
DEBUG_ACTION && console.log(siteStats); | ||
Action.produceReport(site, siteStats, targetFile); | ||
return { site, siteStats, targetFile } | ||
} | ||
|
||
} | ||
|
||
export default Action; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import fetch from 'node-fetch'; | ||
import querystring from 'node:querystring'; | ||
|
||
// DEV debug | ||
const DEBUG_RESPONSE = process.env.UMAMI_DEBUG_RESPONSE === 'true'; | ||
const DEBUG_REQUEST = process.env.UMAMI_DEBUG_REQUEST === 'true'; | ||
|
||
//~ Utils | ||
const arrayIncludesAllOf = (arr, target) => target.every(v => arr.includes(v)); | ||
const isSet = (value) => value !== null && value !== undefined; | ||
const isNotEmptyArray = (value) => isSet(value) && Array.isArray(value) && value.length > 0; | ||
const isUmamiSiteData = (data) => isSet(data) && arrayIncludesAllOf(Object.keys(data), ['website_id', 'website_uuid', 'name', 'domain', 'created_at']); | ||
const givenAuthData = (authData) => { | ||
if (!isSet(authData) || !isSet(authData.token)) { | ||
throw "expect valid auth data to query api"; | ||
} | ||
}; | ||
const rethrow = (err) => {throw err;} | ||
|
||
// Umami API : https://umami.is/docs/api | ||
// TODO : move this util class into a dedicated node-umami-api repository | ||
|
||
class UmamiApi { | ||
|
||
static async login(serverUrl, username, password) { | ||
const authResponse = await fetch(serverUrl+ "/api/auth/login", | ||
{method: 'POST', body: JSON.stringify({username, password}), | ||
headers: {'Content-Type': 'application/json'} | ||
}).catch(rethrow); | ||
if (authResponse.status != 200) { | ||
throw "Invalid login" | ||
} | ||
const authData = await authResponse.json(); | ||
DEBUG_RESPONSE && console.log(authData); | ||
return authData; | ||
} | ||
|
||
static async getSites(serverUrl, authData) { | ||
givenAuthData(authData); | ||
const getSitesResponse = await fetch(serverUrl+ "/api/websites", | ||
{ headers: { "Authorization": `Bearer ${authData.token}`} }).catch(rethrow); | ||
if (getSitesResponse.status != 200) { | ||
throw "Unable to get sites - " + await getSitesResponse.text(); | ||
} | ||
const sitesData = await getSitesResponse.json(); | ||
DEBUG_RESPONSE && console.log(sitesData); | ||
return sitesData; | ||
} | ||
|
||
static selectSiteByDomain(sitesData, siteDomain = '*first*') { | ||
if (!isNotEmptyArray(sitesData)) { | ||
throw "No sites data provided"; | ||
} | ||
if (!isUmamiSiteData(sitesData[0])) { | ||
throw "Unexpected sites data provided"; | ||
} | ||
if (siteDomain === '*first*') { | ||
return sitesData[0]; | ||
} | ||
return sitesData.find( d => d.domain === siteDomain ); | ||
} | ||
|
||
static async getStats(serverUrl, authData, siteData) { | ||
givenAuthData(authData); | ||
if (!isUmamiSiteData(siteData)) { | ||
throw "Unexpected site data provided"; | ||
} | ||
const start_at = Date.now() - (60000 * 60 * 24); | ||
const end_at = Date.now(); | ||
// const statsUrl = serverUrl+ `/api/website/${siteData.website_id}/stats?start_at=${start_at}&end_at=${end_at}`; | ||
const statsUrl = serverUrl+ `/api/website/${siteData.website_id}/stats?` + querystring.stringify({ start_at, end_at }); | ||
DEBUG_REQUEST && console.log(statsUrl); | ||
const getStatsResponse = await fetch(statsUrl, | ||
{ headers: { "Authorization": `Bearer ${authData.token}`} }).catch(rethrow); | ||
if (getStatsResponse.status != 200) { | ||
throw `Unable to get stats - ${getStatsResponse.status} - ` + await getStatsResponse.text(); | ||
} | ||
const sitesStat = await getStatsResponse.json(); | ||
DEBUG_RESPONSE && console.log(sitesStat); | ||
return sitesStat; | ||
} | ||
|
||
} | ||
|
||
export default UmamiApi; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import action from './lib/action.js' | ||
import core from '@actions/core'; | ||
import github from '@actions/github'; | ||
|
||
const umamiServer = core.getInput('umami-server', { required: true }); | ||
var umamiUser = core.getInput('umami-user', { required: true }); | ||
const umamiPassword = core.getInput('umami-password', { required: true }); | ||
const umamiSiteDomain = core.getInput('umami-site-domain');// *first* | ||
const rethrow = (err) => {throw err;}; | ||
const printContext = () => { | ||
// Get the JSON webhook payload for the event that triggered the workflow | ||
const payload = JSON.stringify(github.context.payload, undefined, 2) | ||
console.log(`The event payload: ${payload}`); | ||
}; | ||
try { | ||
if (umamiServer === null || umamiServer === undefined) { | ||
throw "please setup your environment" | ||
} | ||
if (umamiUser === null || umamiUser === undefined) { | ||
umamiUser = 'admin'; | ||
} | ||
// printContext(); | ||
const reportResult = await action.umamiDailyReportV0(umamiServer, umamiUser, umamiPassword, umamiSiteDomain).catch(rethrow); | ||
core.info(`Generated : ${reportResult.targetFile}`); | ||
} catch (error) { | ||
console.info(`ERROR: ${error}`) | ||
core.setFailed(error); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import action from './lib/action.js' | ||
import core from '@actions/core'; | ||
import github from '@actions/github'; | ||
|
||
const UMAMI_SERVER = process.env.UMAMI_SERVER || null; // "https://umami.exemple.com"; | ||
const UMAMI_USER = process.env.UMAMI_USER || "admin"; | ||
const UMAMI_PASSWORD = process.env.UMAMI_PASSWORD || null; | ||
const UMAMI_SITE_DOMAIN = process.env.UMAMI_SITE_DOMAIN || "*first*"; | ||
const rethrow = (err) => {throw err;} | ||
|
||
try { | ||
if (UMAMI_SERVER === null) { | ||
throw "please setup your environment UMAMI_SERVER, UMAMI_USER, UMAMI_PASSWORD, UMAMI_SITE_DOMAIN" | ||
} | ||
const reportResult = await action.umamiDailyReportV0(UMAMI_SERVER, UMAMI_USER, UMAMI_PASSWORD, UMAMI_SITE_DOMAIN) | ||
.catch(rethrow); | ||
console.info(`Generated : ${reportResult.targetFile}`); | ||
} catch (error) { | ||
console.info(`ERROR: ${error}`) | ||
} |
Oops, something went wrong.