-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ITArmy statistics by APIKey. Removed winter theme. Minor improvements
- Loading branch information
Showing
14 changed files
with
583 additions
and
204 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,57 @@ | ||
import fetch, { RequestInit } from 'electron-fetch' | ||
|
||
const BASE_URL = 'https://cossackguard.pp.ua/api' | ||
const BASE_REQUEST_OPTIONS: RequestInit = { | ||
timeout: 10000, // 10 seconds | ||
size: 1024 * 1024 * 10, // 10MB | ||
} | ||
|
||
export interface UserStats { | ||
login: string | ||
totalTraffic: number | ||
createdDate: Date | ||
} | ||
|
||
export interface GetUserStatsRequest { | ||
apiKey: string | ||
} | ||
export interface GetUserStatsResponse { | ||
success: boolean | ||
error: string | ||
errorType: 'OK' | 'BAD_STATUS_CODE' | 'ERR_FROM_BACKEND' | 'REQUEST_FAILED' | ||
data: UserStats | ||
} | ||
|
||
export async function getUserStats(params: GetUserStatsRequest): Promise<GetUserStatsResponse> { | ||
try { | ||
const statsResponse = await fetch(`${BASE_URL}/user/get-user-stats?apiKey=${encodeURI(params.apiKey)}`, BASE_REQUEST_OPTIONS) | ||
if (statsResponse.status !== 200) { | ||
return { | ||
success: false, | ||
errorType: 'BAD_STATUS_CODE', | ||
error: `Bad status code: ${statsResponse.status}. Message: ${await statsResponse.text()}`, | ||
data: undefined as unknown as UserStats | ||
} | ||
} | ||
|
||
const responseJSON = await statsResponse.json() as GetUserStatsResponse | ||
if (!responseJSON.success) { | ||
return { | ||
...responseJSON, | ||
errorType: 'ERR_FROM_BACKEND', | ||
} | ||
} | ||
|
||
if (responseJSON.data?.createdDate) { | ||
responseJSON.data.createdDate = new Date(responseJSON.data?.createdDate) | ||
} | ||
return responseJSON | ||
} catch (err) { | ||
return { | ||
success: false, | ||
errorType: 'REQUEST_FAILED', | ||
error: String(err), | ||
data: undefined as unknown as UserStats | ||
} | ||
} | ||
} |
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,40 @@ | ||
import { UserStats, getUserStats, GetUserStatsResponse } from './api' | ||
|
||
const USERSTATS_CACHE_UPDATE_INTERVAL = 1000 * 30 // 30 seconds | ||
|
||
export class ItArmyClient { | ||
protected userStatsCache?: UserStats | ||
protected userStatsCacheTimestamp?: Date | ||
protected userStatsCacheAPIKeyUsed?: string | ||
|
||
async getUserStats(apiKey: string): Promise<GetUserStatsResponse> { | ||
// Prevent requests with empty API key so the API will not be spammed | ||
if (apiKey === '') { | ||
return { | ||
success: false, | ||
error: 'API key is empty', | ||
errorType: 'REQUEST_FAILED', | ||
data: undefined as unknown as UserStats | ||
} | ||
} | ||
|
||
if (this.userStatsCache && this.userStatsCacheTimestamp && apiKey === this.userStatsCacheAPIKeyUsed && (Date.now() - this.userStatsCacheTimestamp.getTime()) < USERSTATS_CACHE_UPDATE_INTERVAL) { | ||
return { | ||
success: true, | ||
error: '', | ||
errorType: 'OK', | ||
data: this.userStatsCache | ||
} | ||
} | ||
|
||
const response = await getUserStats({ apiKey }) | ||
|
||
if (response.success) { | ||
this.userStatsCache = response.data | ||
this.userStatsCacheTimestamp = new Date() | ||
this.userStatsCacheAPIKeyUsed = apiKey | ||
} | ||
|
||
return response | ||
} | ||
} |
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
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
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,15 @@ | ||
import { Settings } from "./settings"; | ||
import { ItArmyClient } from '../../lib/itarmy/client' | ||
import { ipcMain } from "electron"; | ||
|
||
export function handleItArmy(settings: Settings) { | ||
const client = new ItArmyClient() | ||
|
||
|
||
ipcMain.handle('itarmy:getStats', async () => { | ||
const settingsData = await settings.getData() | ||
const apiKey = settingsData.itarmy.apiKey | ||
|
||
return await client.getUserStats(apiKey) | ||
}) | ||
} |
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
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
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
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,111 @@ | ||
<template> | ||
{{ userName + " | " + selectedModule }} | | ||
<span | ||
:class=" | ||
moduleState == 'RUNNING' | ||
? 'text-positive' | ||
: moduleState == 'ERROR' | ||
? 'text-negative' | ||
: '' | ||
" | ||
>{{ moduleState }}</span | ||
> | ||
| {{ moduleTraffic }} | {{ moduleTotalBytesSend }} | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { ModuleExecutionStatisticsEventData } from "app/lib/module/module"; | ||
import { ExecutionLogEntry } from "app/src-electron/handlers/engine"; | ||
import { IpcRendererEvent } from "electron/renderer"; | ||
import { onBeforeMount, onMounted, onUnmounted, ref } from "vue"; | ||
const userName = ref(""); | ||
const selectedModule = ref(""); | ||
const moduleState = ref(""); | ||
const moduleTraffic = ref(""); | ||
const moduleTotalBytesSend = ref(""); | ||
function humanBytesString(bytes: number, dp = 1) { | ||
const thresh = 1000; | ||
if (Math.abs(bytes) < thresh) { | ||
return bytes + " B"; | ||
} | ||
const units = ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; | ||
let u = -1; | ||
const r = 10 ** dp; | ||
do { | ||
bytes /= thresh; | ||
++u; | ||
} while ( | ||
Math.round(Math.abs(bytes) * r) / r >= thresh && | ||
u < units.length - 1 | ||
); | ||
return bytes.toFixed(dp) + " " + units[u]; | ||
} | ||
async function loadInitialState() { | ||
const executionEngineState = await window.executionEngineAPI.getState(); | ||
selectedModule.value = executionEngineState.moduleToRun || ""; | ||
moduleState.value = executionEngineState.run ? "RUNNING" : "IDLE"; | ||
let bitrate = 0; | ||
if (executionEngineState.statistics.length > 0) { | ||
bitrate = | ||
executionEngineState.statistics[ | ||
executionEngineState.statistics.length - 1 | ||
].currentSendBitrate; | ||
} | ||
moduleTraffic.value = humanBytesString(bitrate) + "/s"; | ||
const response = await window.itArmyAPI.getStats(); | ||
if (response.success) { | ||
moduleTotalBytesSend.value = humanBytesString(response.data.totalTraffic); | ||
} | ||
} | ||
function onExecutionLog(_e: IpcRendererEvent, data: ExecutionLogEntry) { | ||
selectedModule.value = data.moduleName; | ||
if (data.type === "STARTED") { | ||
moduleState.value = "RUNNING"; | ||
} else if (data.type === "STOPPED") { | ||
moduleState.value = "IDLE"; | ||
} else if (data.type === "ERROR") { | ||
moduleState.value = "ERROR"; | ||
} | ||
} | ||
function onStatisticsUpdate( | ||
_e: IpcRendererEvent, | ||
data: ModuleExecutionStatisticsEventData | ||
) { | ||
moduleTraffic.value = humanBytesString(data.currentSendBitrate) + "/s"; | ||
} | ||
async function updateITArmyData() { | ||
const response = await window.itArmyAPI.getStats(); | ||
if (response.success) { | ||
moduleTotalBytesSend.value = humanBytesString(response.data.totalTraffic); | ||
userName.value = response.data.login; | ||
} | ||
} | ||
let updateStatisticsInterval = null as any; | ||
onMounted(async () => { | ||
window.executionEngineAPI.listenForStatistics(onStatisticsUpdate); | ||
window.executionEngineAPI.listenForExecutionLog(onExecutionLog); | ||
await loadInitialState(); | ||
updateStatisticsInterval = setInterval(updateITArmyData, 5000); | ||
}); | ||
onUnmounted(() => { | ||
window.executionEngineAPI.stopListeningForExecutionLog(onExecutionLog); | ||
window.executionEngineAPI.stopListeningForStatistics(onStatisticsUpdate); | ||
if (updateStatisticsInterval) { | ||
clearInterval(updateStatisticsInterval); | ||
} | ||
}); | ||
</script> |
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
Oops, something went wrong.