-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
345 lines (311 loc) · 14.9 KB
/
Program.cs
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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Text.RegularExpressions;
//using System.CodeDom.Compiler;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Edge;
//using OpenQA.Selenium.Support.UI;
namespace geoipdl
{
internal class Program
{
static bool _headless = false;
static bool _pauseOnError = false;
static EdgeDriver _driver = null;
static readonly string _exeDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
static readonly string _driverExe = Path.Combine(_exeDir, "msedgedriver.exe");
static readonly string _driverZip = Path.Combine(_exeDir, "edgedriver_win64.zip");
static readonly string _usersFolder = Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));
static readonly string _edgeUserDataDir = Path.Combine(_usersFolder, $@"{Environment.UserName}\AppData\Local\Microsoft\Edge\User Data");
static readonly string _edgeProfileName = "Selenium";
static readonly string _timestampFile = "TimeStamp.txt";
static readonly string _dlUrl = @"https://gitlab.torproject.org/tpo/network-health/metrics/geoip-data/-/packages";
static readonly string _dlZip = "geoip.zip";
static readonly string[] _dlFiles = { "geoip", "geoip6" };
static string _outDir = ".";
static int _dlInterval = 0;
static string _dlDirectLink = "";
static async Task Main(string[] args)
{
//var cp = new CompilerParameters();
//cp.CompilerOptions = "/optimize /target:winexe /win32icon:icon-reconnect.ico";
try
{
Directory.SetCurrentDirectory(_exeDir);
foreach (string arg in args)
{
if (arg.ToLower() == "--headless")
_headless = true;
if (arg.ToLower() == "--pause-on-error")
_pauseOnError = true;
if (arg.ToLower().Contains("--output-folder="))
{
_outDir = arg.Substring(arg.IndexOf("=") + 1);
_outDir = _outDir.Trim().Trim('"');
}
if (arg.ToLower().Contains("--period-days="))
{
var str = arg.Substring(arg.IndexOf("=") + 1).Trim();
_dlInterval = int.Parse(str);
}
if (arg.ToLower().Contains("--direct-link="))
{
var str = arg.Substring(arg.IndexOf("=") + 1).Trim();
_dlDirectLink = str.Trim('"');
}
}
if (_dlInterval > 0)
{
DateTime currentDate = DateTime.Now;
if (File.Exists(_timestampFile))
{
// Read date from file
DateTime savedDate;
using (StreamReader reader = new StreamReader(_timestampFile))
{
savedDate = DateTime.Parse(reader.ReadLine(), CultureInfo.InvariantCulture);
}
// Compare dates
TimeSpan timeSpan = currentDate.Subtract(savedDate);
if (timeSpan.Days >= _dlInterval)
{
Console.WriteLine($"{_dlInterval} or more days have passed since the saved date.");
}
else
{
//Console.WriteLine($"Less than {_dlInterval} days have passed since the saved date.");
Environment.Exit(0);
}
}
// Save current date to file
using (StreamWriter writer = new StreamWriter(_timestampFile))
{
writer.WriteLine(currentDate.ToString(CultureInfo.InvariantCulture));
}
}
// register Ctrl+C handler
Console.CancelKeyPress += (sender, e) =>
{
//e.Cancel = true; // Cancel the termination process
Console.WriteLine(">> Ctrl+C pressed");
KillDriver();
KillTimeStamp();
};
// Print header
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
Console.Title = fvi.ProductName;
Console.WriteLine("=====================================================================");
Console.WriteLine(fvi.ProductName + " v" + fvi.FileVersion + " github.com/update692/geoip-dl");
Console.WriteLine("=====================================================================");
Console.WriteLine("Download webdriver of the same version as installed Edge browser");
Console.WriteLine("https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/");
Console.WriteLine("=====================================================================");
Console.WriteLine("Optional arguments:");
Console.WriteLine("--headless");
Console.WriteLine("--pause-on-error");
Console.WriteLine(@"--output-folder=""C:\GEOIP\FOLDER""");
Console.WriteLine("--period-days=<DOWNLOAD_INTERVAL>");
Console.WriteLine("--direct-link=https://github.com/update692/geoip/releases/latest/download/geoip.zip");
Console.WriteLine("=====================================================================");
Console.WriteLine("Return errorlevel=0 - success, 1 - error");
Console.WriteLine("=====================================================================");
Console.WriteLine($"Edge user data dir: {_edgeUserDataDir}");
Console.WriteLine($"Edge profile: {_edgeProfileName}");
Console.WriteLine($"Edge driver: {_driverExe}");
Console.WriteLine($"Current directory: {Directory.GetCurrentDirectory()}");
Console.WriteLine($"Output folder: {_outDir}");
Console.WriteLine();
if (!Directory.Exists(_outDir)) throw new ArgumentException("--output-folder does not exist");
if (string.IsNullOrEmpty(_dlDirectLink))
UpdateDriver();
DoMain().GetAwaiter().GetResult();
KillDriver();
}
catch (Exception ex)
{
Console.WriteLine($"{ex.GetType()}: {ex.Message}{Environment.NewLine}{ex.StackTrace}");
KillDriver();
KillTimeStamp();
Console.Out.Flush();
if (_pauseOnError) while (true) await Task.Delay(1000);
Environment.Exit(1);
}
Environment.Exit(0);
}
private static void KillTimeStamp()
{
try
{
if (File.Exists(_timestampFile)) File.Delete(_timestampFile);
}
catch (Exception ex)
{
Console.WriteLine($"Can't delete timestamp file {_timestampFile}{Environment.NewLine}{ex.GetType()}: {ex.Message}{Environment.NewLine}{ex.StackTrace}");
}
}
private static async Task DoMain()
{
if (!string.IsNullOrEmpty(_dlDirectLink))
goto direct_dl;
EdgeOptions edgeOptions = new EdgeOptions();
// Here you set the path of the profile ending with User Data not the profile folder
edgeOptions.AddArgument($"--user-data-dir={_edgeUserDataDir}");
// Here you specify the actual profile folder. If it is Default profile, no need to use this line of code
edgeOptions.AddArgument($"--profile-directory={_edgeProfileName}");
if (_headless)
edgeOptions.AddArgument("headless");
_driver = new EdgeDriver(edgeOptions);
_driver.Manage().Window.Maximize();
_driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(6); // implicit timeout
// go to package page
Console.WriteLine(">> Open site...");
DriverGo(_dlUrl);
var element = _driver.FindElement(By.CssSelector("a.gl-text-body.gl-min-w-0"));
DriverGo(element.GetAttribute("href"));
// find file to download
element = null;
var elements = _driver.FindElements(By.CssSelector("[href*='/-/package_files/']"));
foreach (var el in elements)
{
var children = el.FindElements(By.TagName("span"));
foreach (var e in children)
{
var input = e.Text;
if (Regex.IsMatch(input, @"^geoip-\w{16}\.jar$"))
{
Console.WriteLine(e.Text);
//Console.WriteLine(e.GetAttribute("innerHTML"));
element = el;
goto found_out;
}
}
}
found_out:
if (element == null) throw new Exception("Download link not found");
RunBackgroundConsoleProcess("wget.exe", $@"-O {_dlZip} {element.GetAttribute("href")}");
direct_dl:
if (!string.IsNullOrEmpty(_dlDirectLink))
{
Console.WriteLine(_dlDirectLink);
RunBackgroundConsoleProcess("wget.exe", $@"-O {_dlZip} {_dlDirectLink}");
}
foreach (var file in _dlFiles) if (File.Exists(file)) File.Delete(file);
ExtractFiles(_dlZip, _dlFiles);
foreach (var file in _dlFiles) if (!File.Exists(file)) throw new FileNotFoundException($@"File '{file}' is not found'");
if (_outDir != ".")
foreach (var file in _dlFiles)
File.Copy(file, Path.Combine(_outDir, file), true);
Console.WriteLine(">> OK"); Console.Out.Flush();
await Task.Delay(1500);
}
private static void ExtractFiles(string zipFile, string[] filenames)
{
using (var zip = ZipFile.OpenRead(zipFile))
{
var len = 0;
foreach (string filename in filenames) if (filename.Length > len) len = filename.Length;
len++;
foreach (string filename in filenames)
{
zip.GetEntry(filename)?.ExtractToFile(filename, true);
Console.WriteLine($"{filename}{new string(' ', len - filename.Length)}{File.GetLastWriteTime(filename).ToShortDateString()}");
}
}
}
private static void DriverGo(string url)
{
Console.WriteLine(url);
_driver.Url = url;
}
private static void RunBackgroundConsoleProcess(string exe, string args)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = exe;
startInfo.Arguments = args;
startInfo.UseShellExecute = false; // Required to redirect the standard output and error
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
// Start the process
Process process = new Process();
process.StartInfo = startInfo;
process.OutputDataReceived += Process_OutputDataReceived;
process.ErrorDataReceived += Process_ErrorDataReceived;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
// Wait for the process to end
process.WaitForExit();
process.Close();
process.Dispose();
}
private static void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
Console.WriteLine(e.Data);
}
}
private static void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
Console.WriteLine(e.Data);
}
}
private static void KillDriver()
{
if (_driver != null)
{
_driver.Quit();
_driver.Dispose();
_driver = null;
}
}
private static void UpdateDriver()
{
string edgeVer = GetEdgeVersion();
string driverVer = GetFileVersion(_driverExe);
Console.WriteLine($"Edge version: {edgeVer}");
Console.WriteLine($"Driver version: {driverVer}");
if (string.IsNullOrEmpty(edgeVer)) throw new Exception("Microsoft Edge is not installed");
if (edgeVer == driverVer) return;
// download driver
string driverUrl = GetDriverUrl(GetEdgeVersion());
Console.WriteLine($"Downloading driver");
Console.Write($"{driverUrl} ...");
DownloadFile(driverUrl, _driverZip);
Console.WriteLine();
if (File.Exists(_driverExe)) File.Delete(_driverExe);
ZipFile.ExtractToDirectory(_driverZip, Path.GetDirectoryName(_driverExe));
}
/* Returns null if file not found*/
private static string GetFileVersion(string filePath)
{
string version = null;
if (File.Exists(filePath)) version = FileVersionInfo.GetVersionInfo(filePath).FileVersion;
return version;
}
/* Returns null if keys not found*/
private static string GetEdgeVersion()
{
var reg = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Edge\BLBeacon");
return reg?.GetValue("version")?.ToString();
}
private static string GetDriverUrl(string edgeVersion)
{
return $@"https://msedgedriver.azureedge.net/{edgeVersion}/edgedriver_win64.zip";
}
private static void DownloadFile(string url, string savePath)
{
using (var client = new System.Net.WebClient())
{
client.DownloadFile(url, savePath);
}
}
}
}