-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathdefinition_updater.v2.ahk
213 lines (194 loc) · 7.42 KB
/
definition_updater.v2.ahk
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/**
* @description Class that monitors for updates to the definition
* files used in THQBY's AHK v2 addon for VS Code.
* Use the `Start()` and `Stop()` methods to control the auto-updater.
* @property {Integer} frequency - Set how often, in hours, to check for an update.
* Fractional numbers can be used:
* - `1.5` = 1 hr 30 min
* - `0.1` = 6 min
* Default is `4` hours.
* @property {Integer} notify - Controls if TrayTip notifications show up.
* - `1` = Enable TrayTip notifications
* - `0` = Disable TrayTip notifications
* @property {Integer} update_updater - Enables/disables the auto-updater's own auto-updater.
* - `1` = Allow auto-updater to update itself.
* - `0` = Prevent auto-updater from updating itself.
*/
class _def_enhance_updater {
static version := 1.6
static frequency := 4
static notify := 1
static update_updater := 1
/**
* Run the updater and check regularly on a timer.
*/
static start(*) {
this.running := 1
this.run()
}
/**
* Stops the updater and cancels all timers.
*/
static stop(*) {
this.running := 0
this.run_again('stop')
}
/**
* Forces an update check immediately.
* If running status is false, the timer is disabled after the update check.
* If running status is true, the timer will start fresh after the update check.
*/
static force_check(*) {
running := this.running
this.start()
if !running
this.stop()
}
static file_list := Map(
'dahk', Map(
'url' , 'https://raw.githubusercontent.com/GroggyOtter/ahkv2_definition_rewrite/main/ahk2.d.ahk',
'filename', 'ahk2.d.ahk',
'filetype', 'AHK File (*.ahk)',
'rgx_ver' , ';@region v(\d+)\.(\d+)',
'def_ver' , ';@region v1.0'
),
'json', Map(
'url' , 'https://raw.githubusercontent.com/GroggyOtter/ahkv2_definition_rewrite/main/ahk2.json',
'filename', 'ahk2.json',
'filetype', 'JSON File (*.json)',
'rgx_ver' , '"version": +(\d+)\.(\d+)',
'def_ver' , '"version": 1.0'
),
'updater', Map(
'url' , 'https://raw.githubusercontent.com/GroggyOtter/ahkv2_definition_rewrite/main/definition_updater.v2.ahk',
'filename', 'definition_updater.v2.ahk',
'rgx_ver' , 'static version := (\d+)\.(\d+)',
'def_ver' , 'static version := 1.0'
)
)
static running := 0
static addon_path := ''
static announcement := ''
static __New() {
m := A_TrayMenu
m.Insert('10&')
m.Insert('11&', 'Start Definition Updater', ObjBindMethod(this, 'start'))
m.Insert('12&', 'Stop Definition Updater', ObjBindMethod(this, 'stop'))
m.Insert('13&')
m.Insert('14&', 'Force Definition Update', ObjBindMethod(this, 'force_check'))
m.Insert('15&')
this.start()
}
static run(*) {
this.announcement := ''
if !this.running
return
if !DirExist(this.addon_path)
this.addon_path := this.get_addon_location()
for id, data in this.file_list
if (id = 'updater') && !this.update_updater
continue
else try this.check_for_update(id, data)
if this.announcement
TrayTip(this.announcement
'Reload VS Code for changes to take effect.')
this.run_again()
}
static run_again(stop:=0) {
period := stop ? 0 : Abs(this.frequency * 3600000) * -1
SetTimer(ObjBindMethod(this, 'run'), period)
}
static check_for_update(id, data) {
if (id = 'updater')
file_path := A_ScriptFullPath
else file_path := this.addon_path '\syntaxes\' data['filename']
install_ver := this.get_version(FileRead(file_path), data)
online_txt := this.get_http(data['url'])
if !online_txt
return
online_ver := this.get_version(online_txt, data)
for index, install_num in install_ver {
if (index = 0)
continue
else if (online_ver[index] > install_num) {
name := data['filename']
msg := 'Update available for : ' name
. '`nNew Version: v' online_ver[1] '.' online_ver[2]
. '`nCurrent Version: v' install_ver[1] '.' install_ver[2]
. '`n`nDo you want to update/overwrite this file: '
. '`nThis will move the original file to the recycle bin and replace it with the current one.'
. '`n`nLocation: ' file_path
if (MsgBox(msg, 'AHK Definition Enhancement Update: ' name, 'YesNo') = 'No')
continue
FileRecycle(file_path)
FileAppend(online_txt, file_path, 'UTF-8-RAW')
this.announcement .= name ' has been updated.`n'
break
}
}
}
static get_addon_location() {
addon_path_default := A_AppData '\..\..\.vscode\extensions'
thqby_rgx := 'thqby\.vscode-autohotkey2-lsp-(\d+)\.(\d+)\.(\d+)'
while !DirExist(this.addon_path) {
check_again:
path := ''
v_list := []
loop files addon_path_default '\*', 'D'
if RegExMatch(A_LoopFileFullPath, thqby_rgx)
v_list.Push(A_LoopFileFullPath)
if (v_list.Length = 0) {
addon_path_default := ask_user()
if (addon_path_default = '')
TrayTip('Addon location is not set.`nUpdate check is being skipped.')
,Exit()
goto('check_again')
} else if (v_list.Length = 1)
path := v_list[1]
else
for value in v_list
path := this.get_most_recent(value, path, thqby_rgx)
return path
}
ask_user() => DirSelect('*' A_AppData,
, 'Select the "extensions" folder in the ".vscode" main folder. '
'`nThe default install folder is normally:'
'`nC:\Users\<USERNAME>\.vscode\extensions')
}
static notify_user(msg) => this.notify ? TrayTip(msg) : 0
static get_version(txt, data) {
if !RegExMatch(txt, data['rgx_ver'], &match)
RegExMatch(data['def_ver'], data['rgx_ver'], &match)
return match
}
static get_most_recent(v1, v2, version_rgx) {
switch {
case !v1: return v2
case !v2: return v1
case !RegExMatch(v1, version_rgx, &match1): return v2
case !RegExMatch(v2, version_rgx, &match2): return v1
default:
for key, value in match1
if (key = 0)
continue
else if (match2[key] > value)
return v2
else if (match2[key] < value)
return v1
return v1
}
}
static error(msg) {
if this.notify
TrayTip(msg)
}
static get_http(url) {
timeout := 5
web := ComObject('WinHttp.WinHttpRequest.5.1')
web.Open('GET', url)
web.Send()
if web.WaitForResponse(timeout)
return web.ResponseText
return 0
}
}