using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Memory; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Shared; using Shared.Engine; using Shared.Models.Module; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using IO = System.IO; namespace Lampac.Controllers { public class AdminController : BaseController { #region TryAuthorizeAdmin bool TryAuthorizeAdmin(string passwd, out ActionResult result) { result = null; if (AppInit.rootPasswd == "termux") { HttpContext.Response.Cookies.Append("passwd", "termux"); return true; } if (string.IsNullOrWhiteSpace(passwd)) HttpContext.Request.Cookies.TryGetValue("passwd", out passwd); if (string.IsNullOrWhiteSpace(passwd)) { result = Redirect("/admin/auth"); return false; } string ipKey = $"Accsdb:auth:IP:{requestInfo.IP}"; if (!memoryCache.TryGetValue(ipKey, out ConcurrentDictionary passwds)) { passwds = new ConcurrentDictionary(); memoryCache.Set(ipKey, passwds, DateTime.Today.AddDays(1)); } passwds.TryAdd(passwd, 0); if (passwds.Count > 10) { result = Content("Too many attempts, try again tomorrow."); return false; } if (AppInit.rootPasswd == passwd) return true; HttpContext.Response.Cookies.Delete("passwd"); result = Redirect("/admin/auth"); return false; } #endregion #region admin / auth [HttpGet] [HttpPost] [Route("/admin")] [Route("/admin/auth")] public ActionResult Authorization([FromForm]string parol) { string passwd = parol?.Trim(); if (string.IsNullOrWhiteSpace(passwd)) HttpContext.Request.Cookies.TryGetValue("passwd", out passwd); if (string.IsNullOrWhiteSpace(passwd)) { string html = @" Authorization
Выполните одну из команд через ssh

cat /home/lampac/passwd

docker exec -it lampac cat passwd
"; return Content(html, "text/html; charset=utf-8"); } else { if (!TryAuthorizeAdmin(passwd, out ActionResult badresult)) return badresult; HttpContext.Response.Cookies.Append("passwd", passwd); return renderAdmin(); } } ActionResult renderAdmin() { string adminHtml = IO.File.Exists("wwwroot/mycontrol/index.html") ? IO.File.ReadAllText("wwwroot/mycontrol/index.html") : IO.File.ReadAllText("wwwroot/control/index.html"); return Content(adminHtml, contentType: "text/html; charset=utf-8"); } #endregion #region init [HttpPost] [Route("/admin/init/save")] public ActionResult InitSave([FromForm]string json) { if (!TryAuthorizeAdmin(null, out ActionResult badresult)) return badresult; try { JsonConvert.DeserializeObject(json); } catch (Exception ex) { return Json(new { error = true, ex = ex.Message }); } var jo = JsonConvert.DeserializeObject(json); JToken users = null; var accsdbNode = jo["accsdb"] as JObject; if (accsdbNode != null) { var usersNode = accsdbNode["users"]; if (usersNode != null) { users = usersNode.DeepClone(); accsdbNode.Remove("users"); IO.File.WriteAllText("users.json", JsonConvert.SerializeObject(users, Formatting.Indented)); } } IO.File.WriteAllText("init.conf", JsonConvert.SerializeObject(jo, Formatting.Indented)); return Json(new { success = true }); } [HttpGet] [Route("/admin/init/custom")] public ActionResult InitCustom() { if (!TryAuthorizeAdmin(null, out ActionResult badresult)) return badresult; string json = IO.File.Exists("init.conf") ? IO.File.ReadAllText("init.conf") : null; if (json != null && !json.Trim().StartsWith("{")) json = "{" + json + "}"; var ob = json != null ? JsonConvert.DeserializeObject(json) : new JObject { }; return ContentTo(JsonConvert.SerializeObject(ob)); } [HttpGet] [Route("/admin/init/current")] public ActionResult InitCurrent() { if (!TryAuthorizeAdmin(null, out ActionResult badresult)) return badresult; return Content(JsonConvert.SerializeObject(AppInit.conf), contentType: "application/json; charset=utf-8"); } [HttpGet] [Route("/admin/init/default")] public ActionResult InitDefault() { if (!TryAuthorizeAdmin(null, out ActionResult badresult)) return badresult; return Content(JsonConvert.SerializeObject(new AppInit()), contentType: "application/json; charset=utf-8"); } [HttpGet] [Route("/admin/init/example")] public ActionResult InitExample() { if (!TryAuthorizeAdmin(null, out ActionResult badresult)) return badresult; return Content(IO.File.Exists("example.conf") ? IO.File.ReadAllText("example.conf") : string.Empty); } #endregion #region sync/init [HttpGet] [Route("/admin/sync/init")] public ActionResult Synchtml() { if (!TryAuthorizeAdmin(null, out ActionResult badresult)) return badresult; string html = @" Редактор sync.conf
"; string conf = IO.File.Exists("sync.conf") ? IO.File.ReadAllText("sync.conf") : string.Empty; return Content(html.Replace("{conf}", conf), contentType: "text/html; charset=utf-8"); } [HttpPost] [Route("/admin/sync/init/save")] public ActionResult SyncSave([FromForm] string json) { if (!TryAuthorizeAdmin(null, out ActionResult badresult)) return badresult; try { string testjson = json.Trim(); if (!testjson.StartsWith("{")) testjson = "{" + testjson + "}"; JsonConvert.DeserializeObject(testjson); } catch (Exception ex) { return Json(new { error = true, ex = ex.Message }); } IO.File.WriteAllText("sync.conf", json); return Json(new { success = true }); } #endregion #region manifest [HttpGet] [HttpPost] [Route("/admin/manifest/install")] public Task ManifestInstallHtml(string online, string sisi, string jac, string dlna, string tracks, string ts, string catalog, string merch, string eng) { if (IO.File.Exists("module/manifest.json")) { if (!TryAuthorizeAdmin(null, out ActionResult badresult)) { HttpContext.Response.Redirect("/admin/auth"); return Task.CompletedTask; } } HttpContext.Response.ContentType = "text/html; charset=utf-8"; if (AppInit.rootPasswd == "termux") return HttpContext.Response.WriteAsync("В termux операция недоступна"); bool isEditManifest = false; if (IO.File.Exists("module/manifest.json")) { if (HttpContext.Request.Cookies.TryGetValue("passwd", out string passwd) && passwd == AppInit.rootPasswd) { isEditManifest = true; } else { HttpContext.Response.Redirect("/admin"); return Task.CompletedTask; } } if (HttpContext.Request.Method == "POST") { var modules = new List(10); if (online == "on") modules.Add("{\"enable\":true,\"dll\":\"Online.dll\"}"); if (sisi == "on") modules.Add("{\"enable\":true,\"dll\":\"SISI.dll\"}"); if (!string.IsNullOrEmpty(jac)) { modules.Add("{\"enable\":true,\"initspace\":\"Jackett.ModInit\",\"dll\":\"JacRed.dll\"}"); #region JacRed.conf if (jac == "fdb") { var jacPath = "module/JacRed.conf"; JObject jj; if (IO.File.Exists(jacPath)) { string txt = IO.File.ReadAllText(jacPath).Trim(); if (string.IsNullOrEmpty(txt)) jj = new JObject(); else { if (!txt.StartsWith("{")) txt = "{" + txt + "}"; try { jj = JsonConvert.DeserializeObject(txt) ?? new JObject(); } catch { jj = new JObject(); } } } else { jj = new JObject(); } jj["typesearch"] = "red"; IO.File.WriteAllText(jacPath, JsonConvert.SerializeObject(jj, Formatting.Indented)); } #endregion } if (dlna == "on") modules.Add("{\"enable\":true,\"dll\":\"DLNA.dll\"}"); if (tracks == "on") modules.Add("{\"enable\":true,\"initspace\":\"Tracks.ModInit\",\"dll\":\"Tracks.dll\"}"); if (ts == "on") modules.Add("{\"enable\":true,\"initspace\":\"TorrServer.ModInit\",\"dll\":\"TorrServer.dll\"}"); if (catalog == "on") modules.Add("{\"enable\":true,\"initspace\":\"Catalog.ModInit\",\"dll\":\"Catalog.dll\"}"); if (merch == "on") modules.Add("{\"enable\":false,\"dll\":\"Merchant.dll\"}"); IO.File.WriteAllText("module/manifest.json", $"[{string.Join(",", modules)}]"); if (eng != "on") UpdateInitConf(j => j["disableEng"] = true); if (isEditManifest) { return HttpContext.Response.WriteAsync("Перезагрузите lampac для изменения настроек"); } else { #region frontend cloudflare if (HttpContext.Request.Headers.TryGetValue("CF-Connecting-IP", out var xip) && !string.IsNullOrEmpty(xip)) { UpdateInitConf(j => { var listen = j["listen"] as JObject; if (listen == null) { listen = new JObject(); j["listen"] = listen; } listen["frontend"] = "cloudflare"; }); } #endregion #region htmlSuccess #region shared_passwd string shared_passwd = CrypTo.unic(8).ToLower(); UpdateInitConf(j => { var accsdb = j["accsdb"] as JObject; if (accsdb == null) { accsdb = new JObject(); j["accsdb"] = accsdb; } accsdb["enable"] = true; accsdb["shared_passwd"] = shared_passwd; }); string sharedBlock = $@"
Авторизация в Lampa

Пароль: {shared_passwd}

"; #endregion string htmlSuccesds = $@" Настройка завершена

Настройка завершена

{sharedBlock}
Админ панель

Aдрес: {host}/admin
Пароль: {IO.File.ReadAllText("passwd")}

Media Station X

Settings -> Start Parameter -> Setup
Enter current ip address and port: {HttpContext.Request.Host.Value}

Убрать/Добавить адреса можно в /home/lampac/msx.json

Виджет для Samsung

{host}/samsung.wgt

Для android apk

Зажмите кнопку назад и введите новый адрес: {host}

Плагины для Lampa

Заходим в настройки - расширения, жмем на кнопку ""добавить плагин"". В окне ввода вписываем адрес плагина {host}/on.js и перезагружаем виджет удерживая кнопку ""назад"" пока виджет не закроется.

TorrServer (если установлен)

{host}/ts
"; return HttpContext.Response.WriteAsync(htmlSuccesds).ContinueWith(t => Shared.Startup.appReload.Reload()); #endregion } } #region renderHtml string renderHtml() { var modules = IO.File.Exists("module/manifest.json") ? JsonConvert.DeserializeObject>(IO.File.ReadAllText("module/manifest.json")) : null; string IsChecked(string name, string def) { if (modules == null) return def; bool res = modules.FirstOrDefault(m => m.dll == name)?.enable ?? false; return res ? "checked" : string.Empty; } return $@" Модули
Онлайн балансеры Rezka, Filmix, etc
      ENG балансеры
Клубничка 18+, PornHub, Xhamster, etc
Альтернативные источники каталога cub и tmdb
DLNA - Загрузка торрентов и просмотр медиа файлов с локального устройства
TorrServer - возможность просматривать торренты в онлайн
Tracks - транскодинг видео и замена названий аудиодорожек с rus1, rus2 на читаемые LostFilm, HDRezka, etc
Автоматизация оплаты FreeKassa, Streampay, Litecoin, CryptoCloud


Быстрый поиск по внешним базам JacRed, Rutor, Kinozal, NNM-Club, Rutracker, etc
Локальный jacred.xyz (не рекомендуется ставить на домашние устройства) - 2GB HDD
"; } #endregion return HttpContext.Response.WriteAsync(renderHtml()); } #endregion #region UpdateInitConf void UpdateInitConf(Action modify) { JObject jo; if (IO.File.Exists("init.conf")) { string initconf = IO.File.ReadAllText("init.conf").Trim(); if (string.IsNullOrEmpty(initconf)) jo = new JObject(); else { if (!initconf.StartsWith("{")) initconf = "{" + initconf + "}"; try { jo = JsonConvert.DeserializeObject(initconf) ?? new JObject(); } catch { jo = new JObject(); } } } else { jo = new JObject(); } modify?.Invoke(jo); IO.File.WriteAllText("init.conf", JsonConvert.SerializeObject(jo, Formatting.Indented)); } #endregion } }