When the Profile synchronized by Gist contains ruleListProfile/pacScript, update the corresponding URL content in time #110

This commit is contained in:
proxy.zeroomega 2025-02-24 19:26:16 +08:00
parent 7c47b1f8f9
commit b0ad75d8b2
3 changed files with 50 additions and 17 deletions

View File

@ -50,7 +50,12 @@ class ProxyImpl
) )
profilePac = profilePacCache.get(profile) profilePac = profilePacCache.get(profile)
profilePacKey = referenced_profiles.map( profilePacKey = referenced_profiles.map(
(_profile) -> _profile.name + '_' + (_profile.revision or 1) (_profile) ->
revision = _profile.revision or 1
# remote pacScript and rule list use sha256 to ensue uniqueId
if OmegaPac.Profiles.updateUrl(_profile) and _profile.sha256
revision = _profile.sha256
_profile.name + '_' + revision
).join(',') ).join(',')
if profilePac?[profilePacKey] if profilePac?[profilePacKey]
return profilePac[profilePacKey] return profilePac[profilePacKey]

View File

@ -6,8 +6,25 @@ OmegaPac = require 'omega-pac'
jsondiffpatch = require 'jsondiffpatch' jsondiffpatch = require 'jsondiffpatch'
generateSHA256 = (text) ->
return new Promise((resolve, reject) ->
encoder = new TextEncoder()
data = encoder.encode(text)
crypto.subtle.digest("SHA-256", data).then((hashBuffer) ->
# ArrayBuffer
hashArray = Array.from(new Uint8Array(hashBuffer))
hashHex = hashArray.map((byte) ->
byte.toString(16).padStart(2, '0')).join('')
# SHA-256
resolve(hashHex)
).catch((e) ->
console.log('eee', e)
reject(e)
)
)
PROFILETEMPPACKEY = '__tempZeroRuleListPac' PROFILETEMPPACKEY = '__tempZeroRuleListPac'
transformValueKeys = ['lastUpdate', 'ruleList', 'pacScript', 'sha256']
generateProfileTempPac = (profile) -> generateProfileTempPac = (profile) ->
tempProfile = OmegaPac.Profiles.create(PROFILETEMPPACKEY, profile.profileType) tempProfile = OmegaPac.Profiles.create(PROFILETEMPPACKEY, profile.profileType)
@ -76,7 +93,7 @@ class Options
if OmegaPac.Profiles.updateUrl(value) if OmegaPac.Profiles.updateUrl(value)
profile = {} profile = {}
for k, v of value for k, v of value
continue if k == 'lastUpdate' || k == 'ruleList' || k == 'pacScript' continue if transformValueKeys.indexOf(k) >= 0
profile[k] = v profile[k] = v
value = profile value = profile
return value return value
@ -136,7 +153,8 @@ class Options
@sync.init({gistId, gistToken}).catch((e) -> @sync.init({gistId, gistToken}).catch((e) ->
console.log('sync init fail::', e) console.log('sync init fail::', e)
) )
@_syncWatchStop = @sync.watchAndPull(@_storage) @_syncWatchStop =
@sync.watchAndPull(@_storage, @updateProfile.bind(this))
@sync.copyTo(@_storage).catch(Storage.StorageUnavailableError, => @sync.copyTo(@_storage).catch(Storage.StorageUnavailableError, =>
console.error('Warning: Sync storage is not available in this ' + console.error('Warning: Sync storage is not available in this ' +
'browser! Disabling options sync.') 'browser! Disabling options sync.')
@ -745,16 +763,18 @@ class Options
# rejected by fetchUrl and will not end up here. # rejected by fetchUrl and will not end up here.
# So empty data indicates success without any update (e.g. 304). # So empty data indicates success without any update (e.g. 304).
return profile unless data return profile unless data
profile = OmegaPac.Profiles.byKey(key, @_options) generateSHA256(data).then((dataSHA256) =>
profile.lastUpdate = new Date().toISOString() profile = OmegaPac.Profiles.byKey(key, @_options)
if OmegaPac.Profiles.update(profile, data) profile.lastUpdate = new Date().toISOString()
OmegaPac.Profiles.dropCache(profile) if OmegaPac.Profiles.update(profile, data) or not profile.sha256
OmegaPac.Profiles.updateRevision(profile) profile.sha256 = dataSHA256
changes = {} OmegaPac.Profiles.dropCache(profile)
changes[key] = profile changes = {}
@_setOptions(changes).return(profile) changes[key] = profile
else @_setOptions(changes).return(profile)
return profile else
return profile
)
).catch (reason) -> ).catch (reason) ->
if reason instanceof Error then reason else new Error(reason) if reason instanceof Error then reason else new Error(reason)
@ -1157,7 +1177,8 @@ class Options
@sync.enabled = true @sync.enabled = true
@_syncWatchStop?() @_syncWatchStop?()
@sync.requestPush(@_options) @sync.requestPush(@_options)
@_syncWatchStop = @sync.watchAndPull(@_storage) @_syncWatchStop =
@sync.watchAndPull(@_storage, @updateProfile.bind(this))
if args.useBuiltInSync if args.useBuiltInSync
@sync.toggleBuiltInSync(true) @sync.toggleBuiltInSync(true)
else else

View File

@ -2,7 +2,7 @@
Promise = require 'bluebird' Promise = require 'bluebird'
Storage = require './storage' Storage = require './storage'
Log = require './log' Log = require './log'
{Revision} = require 'omega-pac' {Revision, Profiles} = require 'omega-pac'
jsondiffpatch = require 'jsondiffpatch' jsondiffpatch = require 'jsondiffpatch'
TokenBucket = require('limiter').TokenBucket TokenBucket = require('limiter').TokenBucket
@ -197,7 +197,7 @@ class OptionsSync
# @param {Storage} local The local storage to be written to # @param {Storage} local The local storage to be written to
# @returns {function} Calling the returned function will stop watching. # @returns {function} Calling the returned function will stop watching.
### ###
watchAndPull: (local) -> watchAndPull: (local, updateProfile) ->
pullScheduled = null pullScheduled = null
pull = {} pull = {}
doPull = => doPull = =>
@ -208,7 +208,14 @@ class OptionsSync
Storage.operationsForChanges(changes, base: base, merge: @merge) Storage.operationsForChanges(changes, base: base, merge: @merge)
).then (operations) => ).then (operations) =>
@_logOperations('OptionsSync::pull', operations) @_logOperations('OptionsSync::pull', operations)
local.apply(operations) local.apply(operations).then( ->
updateProfileNames = []
Object.values(operations.set).forEach((profile) ->
if typeof profile is 'object' and Profiles.updateUrl(profile)
updateProfileNames.push(profile.name)
)
updateProfile?(updateProfileNames)
).return(operations)
@storage.watch null, (changes, opts = {}) => @storage.watch null, (changes, opts = {}) =>
for own key, value of changes for own key, value of changes