171 lines
5.5 KiB
C#

using System.Globalization;
using System.Net;
using System.Text;
using System.Xml.Serialization;
using SharpKml.Base;
using SharpKml.Dom;
using SharpKml.Engine;
using skyscraper5.LyngsatMapsScraper.Model;
using skyscraper5.Skyscraper.Scraper.Storage;
using skyscraper8.Skyscraper.Plugins;
using skyscraper8.Skyscraper.Scraper.Storage;
namespace skyscraper5.LyngsatMapsScraper
{
internal class Program
{
static void Main(string[] args)
{
new Program().Run();
}
private XmlSerializer xmlSerializer;
private bool gotHeaders;
private const string rootUrl = "https://genmap.lyngsat.org/server2/kml";
private Random rng;
private void SafeThrottle()
{
if (rng == null)
rng = new Random();
Thread.Sleep(rng.Next(500, 1500));
}
private void Run()
{
PluginLogger logger = PluginLogManager.GetLogger(typeof(Program));
WebClient webClient = new WebClient();
DirectoryInfo outputDirectoryInfo = new DirectoryInfo("temp");
if (!outputDirectoryInfo.Exists)
outputDirectoryInfo.Create();
FileInfo indexJsonFileInfo = outputDirectoryInfo.GetSubfile(String.Format("index_{0}_{1}_{2}.json", DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day));
if (!indexJsonFileInfo.Exists)
{
logger.Log(PluginLogLevel.Info,"download index json");
byte[] kmlByteArray = webClient.DownloadData(rootUrl);
indexJsonFileInfo.WriteAllBytes(kmlByteArray);
SafeThrottle();
}
StorageConnectionManager storageConnectionManager = StorageConnectionManager.GetInstance();
DataStorageFactory dataStorageFactory = storageConnectionManager.GetDefaultDataStorageFactory();
DataStorage storage = dataStorageFactory.CreateDataStorage();
logger.Log(PluginLogLevel.Info,"mark all beams as disabled");
storage.BeamsDisableAll();
IndexJson indexJson = Newtonsoft.Json.JsonConvert.DeserializeObject<IndexJson>(indexJsonFileInfo.ReadAllText());
foreach (IndexJsonKml kml in indexJson.kml_list)
{
SaneSatellitePointer databasePointer = kml.Sanitize();
logger.Log(PluginLogLevel.Info,"mark beam {0} enabled", kml.name);
storage.BeamsEnable(databasePointer.id, databasePointer.satpos, databasePointer.name, databasePointer.beamsProcessTimestamp);
FileInfo kmlFileInfo = outputDirectoryInfo.GetSubfile(String.Format("{0}_{1}_{2}_{3}.kml", kml.satpos, kml.name, kml.id, kml.beams_process_timestamp));
if (!kmlFileInfo.Exists)
{
if (!gotHeaders)
{
webClient.Headers.Add("Referer", rootUrl);
gotHeaders = true;
}
logger.Log(PluginLogLevel.Info,"download {0}", kml.url);
try
{
byte[] kmlData = webClient.DownloadData(kml.url);
kmlFileInfo.WriteAllBytes(kmlData);
SafeThrottle();
}
catch (WebException we)
{
HttpWebResponse httpWebResponse = we.Response as HttpWebResponse;
if (httpWebResponse.StatusCode == HttpStatusCode.NotFound)
{
storage.BeamsDisableSpecific(databasePointer.id, databasePointer.satpos, databasePointer.name, databasePointer.beamsProcessTimestamp);
SafeThrottle();
continue;
}
else
{
logger.Log(PluginLogLevel.Error,we.ToString());
throw;
}
}
catch (Exception e)
{
logger.Log(PluginLogLevel.Error, e.ToString());
throw;
}
}
FileStream kmlStream = kmlFileInfo.OpenRead();
KmlFile kmlFile = KmlFile.Load(kmlStream);
Document rootFeature = (SharpKml.Dom.Document)((SharpKml.Dom.Kml)kmlFile.Root).Feature;
foreach (Feature feature in rootFeature.Features)
{
Placemark placemark = feature as Placemark;
if (placemark == null)
continue;
string name = placemark.Name;
Polygon polygon = placemark.Geometry as Polygon;
if (polygon == null)
continue;
string id = polygon.Id;
CoordinateCollection linearRingCoordinates = polygon.OuterBoundary.LinearRing.Coordinates;
StringBuilder sb = new StringBuilder();
foreach (Vector vector in linearRingCoordinates)
{
sb.AppendFormat("{0},{1}\t", vector.Longitude.ToString(CultureInfo.InvariantCulture), vector.Latitude.ToString(CultureInfo.InvariantCulture));
}
string polygonString = sb.ToString().Trim('\t');
if (string.IsNullOrEmpty(polygonString))
continue;
Skyscraper.Drawing.Polygon testPolygon = new Skyscraper.Drawing.Polygon(polygonString);
string polygonString2 = testPolygon.GetPolygonString();
if (!polygonString2.Equals(polygonString))
{
throw new ApplicationException("Oh dear, I think we're encountering a bug.");
}
if (!storage.TestForBeamFootprint(databasePointer.id, databasePointer.beamsProcessTimestamp, name, id))
{
logger.Log(PluginLogLevel.Info,"write footprint {0}", name);
storage.BeamFootprintStore(databasePointer.id, databasePointer.beamsProcessTimestamp, name, polygonString2, id);
}
}
kmlStream.Close();
}
}
}
internal static class DirectoryInfoExtensions
{
public static FileInfo GetSubfile(this DirectoryInfo directory, string filename)
{
string path = Path.Combine(directory.FullName, filename);
return new FileInfo(path);
}
}
internal static class FileInfoExtensionis
{
public static void WriteAllBytes(this FileInfo fileInfo, byte[] bytes)
{
File.WriteAllBytes(fileInfo.FullName, bytes);
}
public static byte[] ReadAllBytes(this FileInfo fileInfo)
{
return File.ReadAllBytes(fileInfo.FullName);
}
public static string ReadAllText(this FileInfo fileInfo)
{
return File.ReadAllText(fileInfo.FullName);
}
}
}