221 lines
5.9 KiB
C#
221 lines
5.9 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Net;
|
||
using System.Text;
|
||
using System.Text.RegularExpressions;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using System.Web.Caching;
|
||
using System.Web.Hosting;
|
||
using FSLib.Network.Http;
|
||
using Newtonsoft.Json;
|
||
using TrainInfomationProviderService.StationInfo.Entities;
|
||
|
||
namespace TrainInfomationProviderService.StationInfo
|
||
{
|
||
using TrainInfomationProviderService.Web;
|
||
|
||
/// <summary>
|
||
/// </summary>
|
||
public class StationManager
|
||
{
|
||
private static readonly object _lockObject = new object();
|
||
private static StationManager _stationManager;
|
||
|
||
public static StationManager Instance
|
||
{
|
||
get
|
||
{
|
||
if (_stationManager == null)
|
||
{
|
||
lock (_lockObject)
|
||
{
|
||
if (_stationManager == null)
|
||
{
|
||
_stationManager = new StationManager();
|
||
}
|
||
}
|
||
}
|
||
|
||
return _stationManager;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建 <see cref="StationManager" /> 的新实例(StationManager)
|
||
/// </summary>
|
||
public StationManager()
|
||
{
|
||
Trace.TraceInformation("[STATION] 车站管理器对象已新建");
|
||
}
|
||
|
||
|
||
private string _dataFilePath;
|
||
|
||
/// <summary>
|
||
/// 仓库
|
||
/// </summary>
|
||
public StationStorage Storage
|
||
{
|
||
get
|
||
{
|
||
return _storage;
|
||
}
|
||
}
|
||
|
||
public void Init()
|
||
{
|
||
Trace.TraceInformation("[STATION] 正在初始化");
|
||
|
||
_dataFilePath = PathUtility.Combine(RunTimeContext.DataStorageRoot, "stations.json");
|
||
Trace.TraceInformation("[STATION] 目标缓存文件路径:{0}", _dataFilePath);
|
||
|
||
//if (RunTimeContext.IsWeb)
|
||
//{
|
||
// Trace.TraceInformation("[STATION] WEB模式");
|
||
|
||
// InitWeb();
|
||
//}
|
||
//else
|
||
//{
|
||
Trace.TraceInformation("[STATION] 服务模式");
|
||
InitService();
|
||
//}
|
||
}
|
||
|
||
#region web环境
|
||
|
||
///// <summary>
|
||
///// web环境初始化
|
||
///// </summary>
|
||
//void InitWeb()
|
||
//{
|
||
// Trace.TraceInformation("[STATION] 初始化WEB模式");
|
||
// LoadCache();
|
||
//}
|
||
|
||
//void LoadCache()
|
||
//{
|
||
// Trace.TraceInformation("[STATION] 正在检查缓存刷新");
|
||
// _storage = null;
|
||
// if (File.Exists(_dataFilePath))
|
||
// {
|
||
// Trace.TraceInformation("[STATION] 正在加载缓存");
|
||
// _storage = JsonConvert.DeserializeObject<StationStorage>(File.ReadAllText(_dataFilePath));
|
||
// Trace.TraceInformation("[STATION] 缓存加载完成");
|
||
// }
|
||
|
||
// if (Storage != null)
|
||
// {
|
||
// Trace.TraceInformation("[STATION] 正在加入HttpRuntime缓存");
|
||
// HostingEnvironment.Cache.Add("_12306stations", Storage, new CacheDependency(_dataFilePath),
|
||
// Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.High,
|
||
// (_1, _2, _3) =>
|
||
// {
|
||
// Trace.TraceInformation("[STATION] HttpRuntime缓存已被清除,原因:{0},正在重新加载", _3);
|
||
// LoadCache();
|
||
// });
|
||
// Trace.TraceInformation("[STATION] HttpRuntime缓存加入完成");
|
||
// }
|
||
//}
|
||
|
||
|
||
#endregion
|
||
|
||
#region 服务模式
|
||
|
||
private Timer _checkStationTimer;
|
||
private StationStorage _storage;
|
||
|
||
/// <summary>
|
||
/// 服务模式初始化
|
||
/// </summary>
|
||
void InitService()
|
||
{
|
||
if (_dataFilePath.AsFileInfo().Exists)
|
||
{
|
||
Trace.TraceInformation("[STATION] 正在加载文件缓存数据");
|
||
_storage = JsonConvert.DeserializeObject<StationStorage>(File.ReadAllText(_dataFilePath));
|
||
Trace.TraceInformation("[STATION] 文件缓存数据加载完成");
|
||
}
|
||
var lastestVersion = GetLatestVersionFromWeb();
|
||
var needUpdate = _storage == null || _storage.Version < lastestVersion;
|
||
Trace.TraceInformation("[STATION] 最新版本:{0}", lastestVersion);
|
||
|
||
if (needUpdate)
|
||
{
|
||
Trace.TraceInformation("[STATION] 正在刷新缓存");
|
||
RefreshStationInfo(lastestVersion);
|
||
SameStationManager.AutoRefreshFromSource();
|
||
Trace.TraceInformation("[STATION] 缓存数据已刷新");
|
||
}
|
||
_checkStationTimer = new Timer(_ => CheckStationVersion(), null, new TimeSpan(0, 30, 0), Timeout.InfiniteTimeSpan);
|
||
}
|
||
|
||
void RefreshStationInfo(int version)
|
||
{
|
||
Trace.TraceInformation("[STATION] 正在获得最新车站信息");
|
||
var html = new HttpWebClient().Create(HttpMethod.Get, "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js", null, null, "").Send();
|
||
if (!html.IsValid())
|
||
{
|
||
Trace.TraceError("[STATION] 车站信息获得失败。错误:{0}", html.Exception);
|
||
|
||
return;
|
||
}
|
||
Trace.TraceInformation("[STATION] 正在分析车站信息");
|
||
|
||
var mcs = Regex.Matches(html.Result, @"@([^\|]+)\|([^\|]+)\|([^\|]+)\|([^\|]+)\|([^\|]+)\|(\d+)");
|
||
var result = new List<StationDetailInfo>(mcs.Count);
|
||
foreach (Match mc in mcs)
|
||
{
|
||
var s = new StationDetailInfo()
|
||
{
|
||
Code = mc.GetGroupValue(3),
|
||
Name = mc.GetGroupValue(2),
|
||
Py = mc.GetGroupValue(5),
|
||
PyFull = mc.GetGroupValue(4),
|
||
Sort = mc.GetGroupValue(6).ToInt32()
|
||
};
|
||
result.Add(s);
|
||
}
|
||
_storage = new StationStorage(version, result);
|
||
Trace.TraceInformation("[STATION] 车站信息分析完成,{0} 车站。正在缓存车站信息", result.Count);
|
||
|
||
//save
|
||
File.WriteAllText(_dataFilePath, JsonConvert.SerializeObject(Storage));
|
||
Trace.TraceInformation("[STATION] 车站信息缓存完成。目标文件 {0}", _dataFilePath);
|
||
}
|
||
|
||
void CheckStationVersion()
|
||
{
|
||
var lastestVersion = GetLatestVersionFromWeb();
|
||
if (Storage == null || Storage.Version < lastestVersion)
|
||
{
|
||
RefreshStationInfo(lastestVersion);
|
||
}
|
||
_checkStationTimer.Change(new TimeSpan(0, 30, 0), Timeout.InfiniteTimeSpan);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从网络加载最新的版本号
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public int GetLatestVersionFromWeb()
|
||
{
|
||
var ctx = new HttpWebClient().Create<string>(HttpMethod.Get, "https://kyfw.12306.cn/otn/leftTicket/init", "https://kyfw.12306.cn/otn/leftTicket/init").Send();
|
||
if (!ctx.IsValid())
|
||
return 0;
|
||
|
||
var version = (int)(Regex.Match(ctx.Result, @"station_name\.js\?station_version=([\d\.]+)").GetGroupValue(1).ToSingle() * 100000);
|
||
|
||
return version;
|
||
}
|
||
|
||
|
||
#endregion
|
||
}
|
||
}
|