add update notification campaign

This commit is contained in:
Jonas Lochmann
2026-07-13 02:00:00 +02:00
parent ccfbf97d36
commit 893f3664cf
2 changed files with 72 additions and 1 deletions
@@ -0,0 +1,64 @@
/*
* server component for the TimeLimit App
* Copyright (C) 2019 - 2026 Jonas Lochmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { createHash } from 'crypto'
const updateMessage =
'Please update the TimeLimit App to the latest release. ' +
'In your current version, synchronization and purchases may not work as expected.' +
'\n\n' +
'Bitte die TimeLimit-App aktualisieren. ' +
'Mit der momentan installierten Version kann es zu Einschränkungen bei der Synchronisation und bei Käufen kommen.'
export function getCampaign({ familyId, isClient750OrNewer }: {
familyId: string
isClient750OrNewer: boolean
}): string | undefined {
const now = Date.now()
const campaigns = [
{
enable: !isClient750OrNewer,
seed: 'Q05NwM4nyUfiYg6K', // require('crypto').randomBytes(12).toString('base64')
startTime: 1784160000000, // new Date('2026-07-16').valueOf()
endTime: 1785369600000, // new Date('2026-07-30').valueOf()
startPercentage: 0,
endPercentage: 10,
message: updateMessage,
}
]
for (const campaign of campaigns) {
if (!campaign.enable) continue
if (now < campaign.startTime) continue
const progress = Math.min((now - campaign.startTime) / (campaign.endTime - campaign.startTime), 1)
const chanceInPercent = campaign.startPercentage + progress * (campaign.endPercentage - campaign.startPercentage)
const hasher = createHash('SHA3-224')
hasher.update(campaign.seed, 'base64')
hasher.update(familyId)
const hash = hasher.digest().readUInt32BE(0)
const match = hash < chanceInPercent * Math.pow(2, 32) / 100
if (match) return campaign.message
}
return undefined
}
@@ -22,6 +22,7 @@ import { getStatusMessage } from '../../../function/statusmessage'
import { ClientDataStatus } from '../../../object/clientdatastatus'
import { ServerDataStatus } from '../../../object/serverdatastatus'
import { EventHandler } from '../../../monitoring/eventhandler'
import { getCampaign } from './campaign'
import {
getCategoryAssignedApps, getCategoryBaseDatas, getCategoryDataToSync,
getRules, getTasks, getUsedTimes
@@ -54,12 +55,18 @@ export const generateServerDataStatus = async ({
const doesClientSupportDh = clientLevel >= 5
const doesClientSupportU2f = clientLevel >= 6
const doesClientSupportPing = clientLevel >= 7
const isClient750OrNewer = clientLevel >= 8 // first release in the post gplay time
const message: string | undefined =
await getStatusMessage({ database, transaction }) ||
getCampaign({ familyId, isClient750OrNewer }) ||
undefined
const result: ServerDataStatus = {
fullVersion: config.alwaysPro ? 1 : (
familyEntry.hasFullVersion ? parseInt(familyEntry.fullVersionUntil, 10) : 0
),
message: await getStatusMessage({ database, transaction }) || undefined,
message,
apiLevel: 9
}