public void UpdateUser(RayPortUser configToModify) { if (configToModify == null) { throw new ArgumentException(nameof(configToModify)); } JObject configJObj = GetRayConfigJObject(); if (configJObj == null) { throw new Exception("无法读取配置文件."); } int portNum = GetRayPort(configToModify).Port; JArray usersJObj = configJObj .SelectToken( $"inbounds[?(@port == {portNum})].settings.clients") as JArray; if (!(usersJObj .SelectToken($"$.[?(@.id == '{configToModify.Uuid}')]") is JObject userToModifyJObj)) { throw new Exception($"找不到指定的用户!{configToModify}"); } int pos = usersJObj.IndexOf(userToModifyJObj); usersJObj.Remove(userToModifyJObj); usersJObj.Insert(pos, configToModify.ToJObject(RayConfigJsonSetting.JsonSerializer)); WriteJsonToFile(configJObj); }
public void DeleteRayPortUser(RayPortUser rayPortUser) { var rayPort = GetRayPort(rayPortUser); var rayConfigObj = GetRayConfigJObject(); if (!(rayConfigObj.SelectToken( $"inbounds[?(@port == {rayPort.Port})].settings.clients") is JArray rayUsersObj)) { throw new ArgumentException($"找不到用户{rayPortUser.GetRayPortUserRemark()}"); } var rayUserObjtoDelete = rayUsersObj.SelectToken($"$.[?(@.id == '{rayPortUser.Uuid}')]"); if (rayUserObjtoDelete == null) { throw new ArgumentException($"找不到用户{rayPortUser.GetRayPortUserRemark()}"); } if (!rayUsersObj.Remove(rayUserObjtoDelete)) { throw new Exception($"Failed to remove {rayUserObjtoDelete.ToString()}"); } WriteJsonToFile(rayConfigObj); }
public static void DisplayUser( RayPortUser rayPortUser, int?index = null, bool showShareUrl = true, bool addReturn = true, int intend = 2) { if (rayPortUser == null) { return; } StringBuilder s = new StringBuilder(""); StringWriter sw = new StringWriter(s); s.Append(' ', intend); Displayer.ShowConfigItem(s + "索引", index, Program.HighLightColor); Displayer.ShowConfigItem(s + "用户", rayPortUser.GetRayPortUserRemark(), Program.WarningColor); Displayer.ShowConfigItem(s + "用户Id", rayPortUser.Uuid); Displayer.ShowConfigItem(s + "用户额外Id", rayPortUser.AlterId); Displayer.ShowConfigItem(s + "等级(Level)", rayPortUser.Level); Displayer.ShowConfigItem(s + "邮箱", rayPortUser.Email); if (showShareUrl) { try { Displayer.ShowConfigItem( "分享链接", rayPortUser.GenerateShareUrl(RayConfigRepository.GetRayPort(rayPortUser)), Program.ErrorColor); } catch (Exception) { } } if (addReturn) { Console.WriteLine(); } }
public static void UpdateUser(string uuid, RayPortUser rayPortUser) { RayConfigRepository repo = new RayConfigRepository(); var rayPort = repo.GetRayPorts() .FirstOrDefault( o => o.Settings .Clients ?.Contains(rayPortUser, RayPortUserEqualityComparer.Default) ?? false); var rayPortUsers = rayPort.Settings.Clients; int index = rayPortUsers.IndexOf( rayPortUsers.FirstOrDefault(r => r.Uuid == uuid)); int port = rayPort.Port; JObject rayConfigObj = repo.GetRayConfigJObject(); JArray clientsObj = rayConfigObj.SelectToken($"inbounds[?(@port == {port})].settings.clients") as JArray; if (!(rayConfigObj .SelectToken($"inbounds[?(@port == {port})].settings.clients[?(@id == '{uuid}')]") is JObject clientObjToUpdate)) { return; } clientsObj.Remove(clientObjToUpdate); clientsObj.Insert(index, JObject.FromObject(rayPortUser, RayConfigJsonSetting.JsonSerializer)); WriteJsonToFile(rayConfigObj); }
public void AddForbiddenUser(RayPort port, RayPortUser user) { JObject rootJObj = this.rootJObj; RayConfigExtension configEx = JsonConvert.DeserializeObject <RayConfigExtension>( rootJObj.ToString()); if (configEx.ForbiddenedUsersPorts == null) { configEx.ForbiddenedUsersPorts = new List <RayPort>(); } else if (!configEx.ForbiddenedUsersPorts.Contains( port, RayPortEqualityComparer.Default)) { configEx.ForbiddenedUsersPorts.Add(port); } RayPort p = configEx.ForbiddenedUsersPorts.FirstOrDefault( r => r.Port == port.Port); ((p.Settings ??= new RayPortSettings()) .Clients ??= new List <RayPortUser>()).Add(user); SaveConfigEx(configEx); }
/// <summary> /// 生成 V2ray 分享链接 /// </summary> /// <param name="rayPortUser"></param> /// <param name="rayPort"></param> /// <returns></returns> public static string GenerateShareUrl(this RayPortUser rayPortUser, RayPort rayPort) { ClientUserConfig clientConfig = new ClientUserConfig(rayPort, rayPortUser); string jStr = clientConfig.ToJsonString(RayConfigJsonSetting.JsonSerializerSettings); return("vmess://" + Convert.ToBase64String(Encoding.Default.GetBytes(jStr))); }
public void Execute() { RayConfigRepository repo = new RayConfigRepository(); IList <RayPort> ports = repo.GetRayPorts(); ConsoleConfigDisplayer.DisplayRayPorts(ports); try { int ch = InputHelper.GetNumberInput("输入端口索引选择端口", tipsColor: ConsoleColor.DarkGreen); ch -= 1; if (ch >= ports.Count) { Displayer.ShowLine("输入错误, 超出索引.", ConsoleColor.Red); return; } ConsoleInputRayPortConfigBuilder rayPortBuilder = new ConsoleInputRayPortConfigBuilder(ports[ch]); RayPortUser user = rayPortBuilder.BuildPortUser(); repo.AddUserToPort(ports[ch], user); Displayer.ShowLine("操作成功!", ConsoleColor.DarkGreen, true); ConsoleConfigDisplayer.DisplayUser(user); } catch (Exception ex) { Displayer.ShowLine($"操作失败!\r\n错误:{ex.Message}", ConsoleColor.Red, true); } }
public static string GetRayPortUserRemark(this RayPortUser rayPortUser) { // rayPortUser.Email.Split('@') Regex regex = new Regex("^.*(?=@)"); if (string.IsNullOrEmpty(rayPortUser.Email)) { rayPortUser.Email = (new Random()).Next(1, int.MaxValue).ToString() + "@la.aggage"; RayConfigRepository.UpdateUser(rayPortUser.Uuid, rayPortUser); } return(regex.Match(rayPortUser.Email)?.Value ?? ""); }
/// <summary> /// 获取用户使用的上行流量 /// </summary> /// <param name="user">用户</param> /// <returns>用户的上行流量</returns> public long GetUpLinkTraffic(RayPortUser user) { string output = RunV2Ctl( "/usr/bin/v2ray/v2ctl", string.Format( "api --server=127.0.0.1:13888 StatsService.QueryStats \"pattern: 'user>>>{0}>>>traffic>>>uplink' reset: false\"", user.Email)); Regex regex = new Regex("(?<=value: )[0-9]*"); string traffic = regex.Match(output).Value; return(long.Parse(traffic)); }
public void AddUserToPort(RayPort rayPort, RayPortUser user) { var rayConfigObj = GetRayConfigJObject(); if (!(rayConfigObj.SelectToken($"inbounds[?(@port == {rayPort.Port})].settings.clients") is JArray rayPortUsersObj)) { throw new ArgumentException(nameof(rayPort), "端口不存在, 请创建端口"); } JObject userObj = JObject.FromObject(user, RayConfigJsonSetting.JsonSerializer); rayPortUsersObj.Add(userObj); WriteJsonToFile(rayConfigObj); }
public static RayPort GetRayPort(RayPortUser rayPortUser) { var repo = new RayConfigRepository(); var rayPorts = repo.GetRayPorts(); RayPort rayPort = null; foreach (var r in rayPorts) { if (r.Settings?.Clients?.Any(obj => obj.Uuid == rayPortUser.Uuid) ?? false) { rayPort = r; break; } } return(rayPort); }
private void ShowRayPortsUsersAndGetRayPortUserToDelete() { IList <RayPortUser> rayPortsUsers = repo.GetRayPortsUsers(); Console.Clear(); ConsoleConfigDisplayer.DisplayRayPortUsers( rayPortsUsers, displayUserIndex: true, intend: 2); int?ch = InputHelper.TryGetNumberInput( "输入索引来选择要删除的用户", inputRange: new Tuple <int, int>(1, rayPortsUsers.Count)); if (ch == null) { throw new Exception($"输入错误, 输入范围必须是1-{rayPortsUsers.Count}的数字"); } rayPortUserToDelete = rayPortsUsers[ch.Value - 1]; }
public static string QueryTraffic(this RayPortUser user) { var psi = new ProcessStartInfo("dotnet", "--info") { RedirectStandardOutput = true }; var proc = Process.Start(psi); if (proc == null) { Displayer.ShowLine("Failed to query traffic"); } else { using var sr = proc.StandardOutput; string text = sr.ReadToEnd(); } throw new NotImplementedException(); }
/// <summary> /// 显示用户流量统计 /// </summary> /// <param name="user"></param> private void DisplayUserTrafficStatistics(RayPortUser user) { Displayer.ShowLine( user.GetRayPortUserRemark() + ": ", addReturn: true, color: ConsoleColor.Yellow); Displayer.ShowConfigItem( "上行流量", repo.GetUpLinkTraffic(user).ToTrafficString(), valueColor: Displayer.HighLightColor, addReture: true); Displayer.ShowConfigItem( "下行流量", repo.GetDownloadLinkTraffic(user).ToTrafficString(), valueColor: Displayer.HighLightColor, addReture: true); Displayer.ShowConfigItem( "已使用总流量", repo.GetTraffic(user).ToTrafficString(), valueColor: Displayer.HighLightColor, addReture: true); }
public IRayPortConfigBuilder BuildClients() { RayPort.Settings = RayPort.Settings ?? new RayPortSettings(); RayPort.Settings.Clients = RayPort.Settings.Clients ?? new List <RayPortUser>(); RayPortUser client = new RayPortUser(); RayPort.Settings.Clients.Add(client); try { client.Email = InputHelper.GetInput("用户名", "不能包含 @ 字符"); Displayer.ShowLine("设置成功! " + client.Email + "\r\n", ConsoleColor.DarkGreen); client.Email += "@t.tt"; client.Uuid = InputHelper.GetInput("用户id", "默认 - " + client.Uuid); Displayer.ShowLine("设置成功! " + client.Uuid + "\r\n", ConsoleColor.DarkGreen); client.Uuid = string.IsNullOrEmpty(client.Uuid) ? Guid.NewGuid().ToString() : client.Uuid; client.AlterId = InputHelper.GetNumberInput("额外id", "默认 - " + client.AlterId.ToString()); } catch { client.Uuid = Guid.NewGuid().ToString(); client.AlterId = 64; } finally { Displayer.ShowLine("设置成功! " + client.AlterId + "\r\n", ConsoleColor.DarkGreen); } return(this); }
public void AddForbiddenUser(int portNumber, RayPortUser user) { AddForbiddenUser(new RayPort { Port = portNumber }, user); }
/// 获取用户使用的总流量, 包括上行流量和下行流量 /// </summary> /// <param name="user">查询的用户</param> /// <returns>用户已使用的流量, 包括上行和下行流量, 单位为B(字节)</returns> public long GetTraffic(RayPortUser user) { return(GetDownloadLinkTraffic(user) + GetUpLinkTraffic(user)); }