packages.xinli: init

This commit is contained in:
2025-09-14 12:18:26 +08:00
parent 05a333756d
commit 238934ad36
8 changed files with 147 additions and 3 deletions

6
flake.lock generated
View File

@@ -845,11 +845,11 @@
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1757797135,
"narHash": "sha256-zwE/e7CuPJUWKdvvTCB7iunV4E/+G0lKfv4kk/5Izdg=",
"lastModified": 1757823305,
"narHash": "sha256-goy+ZVzBAe/cN/Udsiqg7RdNA19jyJqO8x6KXnZ8Mfs=",
"owner": "CHN-beta",
"repo": "nixpkgs",
"rev": "1c9ddb7f7b4d79fd290561ffb3be03fb493c5c81",
"rev": "db545f2ed84e23a80610792162a7a8adc888dcae",
"type": "github"
},
"original": {

View File

@@ -48,4 +48,11 @@
CMAKE_EXPORT_COMPILE_COMMANDS = "1";
hardeningDisable = [ "all" ];
};
xinli = pkgs.mkShell.override { stdenv = pkgs.clang18Stdenv; }
{
inputsFrom = [ pkgs.localPackages.xinli ];
packages = [ pkgs.clang-tools_18 ];
CMAKE_EXPORT_COMPILE_COMMANDS = "1";
hardeningDisable = [ "all" ];
};
}

View File

@@ -145,6 +145,8 @@ inputs: rec
speedtest = inputs.pkgs.callPackage ./speedtest.nix { src = inputs.topInputs.speedtest; };
atat = inputs.pkgs.callPackage ./atat.nix { src = inputs.topInputs.self.src.atat; };
atomkit = inputs.pkgs.callPackage ./atomkit.nix { src = inputs.topInputs.self.src.atomkit; };
xinli = inputs.pkgs.callPackage ./xinli
{ inherit biu; stdenv = inputs.pkgs.clang18Stdenv; inherit (inputs.pkgs.pkgs-unstable) httplib; };
fromYaml = content: builtins.fromJSON (builtins.readFile
(inputs.pkgs.runCommand "toJSON" {}

1
packages/xinli/.envrc Normal file
View File

@@ -0,0 +1 @@
use flake .#xinli

1
packages/xinli/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
config.yaml

View File

@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.14)
project(xinli VERSION 0.0.0 LANGUAGES CXX)
enable_testing()
include(GNUInstallDirs)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message("Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
find_package(biu REQUIRED)
find_package(httplib REQUIRED)
find_package(nlohmann_json REQUIRED)
add_executable(xinli src/main.cpp)
target_compile_features(xinli PUBLIC cxx_std_23)
target_link_libraries(xinli PRIVATE biu::biu httplib::httplib nlohmann_json::nlohmann_json)
install(TARGETS xinli RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
get_property(ImportedTargets DIRECTORY "${CMAKE_SOURCE_DIR}" PROPERTY IMPORTED_TARGETS)
message("Imported targets: ${ImportedTargets}")
message("List of compile features: ${CMAKE_CXX_COMPILE_FEATURES}")

View File

@@ -0,0 +1,7 @@
{ lib, stdenv, cmake, pkg-config, biu, httplib, nlohmann_json }: stdenv.mkDerivation
{
name = "xinli";
src = ./.;
buildInputs = [ biu httplib nlohmann_json ];
nativeBuildInputs = [ cmake pkg-config ];
}

103
packages/xinli/src/main.cpp Normal file
View File

@@ -0,0 +1,103 @@
# include <biu.hpp>
# include <httplib.h>
# include <nlohmann/json.hpp>
using namespace biu::literals;
int main(int argc, char **argv)
{
biu::Logger::Guard log;
struct Job_t { std::string Type; YAML::Node Params; };
struct { std::string Cookie; std::vector<Job_t> Jobs; } Config;
Config = YAML::LoadFile(argv[1]).as<decltype(Config)>();
log.debug("read cookie: {}"_f(Config.Cookie));
httplib::Client cli("https://xmuxg.xmu.edu.cn");
auto get = [&](const std::string &url, httplib::Params params = {}) -> std::optional<std::string>
{
biu::Logger::Guard log;
auto res = cli.Get(url, params, {{"Cookie", Config.Cookie}});
if (res && res->status == 200) return log.rtn(res->body);
else { log.error("failed to get {}: {}"_f(url, res ? res->status : 0)); return {}; }
};
auto post = [&](const std::string &url, const std::string &body) -> std::optional<std::string>
{
biu::Logger::Guard log;
auto res = cli.Post
(url, {{"Cookie", Config.Cookie}}, body, "application/json");
if (res && res->status == 200) return log.rtn(res->body);
else { log.error("failed to post {}: {}"_f(url, res ? res->status : 0)); return {}; }
};
std::map<std::string, std::pair<std::string, std::string>> Campus =
{
{"翔安", {"1", "RESERVATION"}},
{"思明", {"2", "RESERVATION"}},
{"漳州", {"1588748384174", "RESERVATION"}},
{"线上", {"1588748384174", "ONLINE"}},
};
for (const auto &job : Config.Jobs)
{
if (job.Type == "AddSchedule")
{
struct { std::string Campus, Name, Date, Time; } params;
params = job.Params.as<decltype(params)>();
if (!Campus.contains(params.Campus)) { log.error("unknown campus: {}"_f(params.Campus)); continue; }
// 搜索老师id
auto teacherId = [&] -> std::optional<std::string>
{
auto res = get
("/api/mentality/teachers/searchResults", {{"keyword", params.Name}});
if (!res) return {};
for (auto teach : YAML::Load(*res)["data"])
if (teach["name"].as<std::string>() == params.Name)
return log.rtn(teach["userId"].as<std::string>());
log.error("teacher not found: {}"_f(params.Name));
return {};
}();
if (!teacherId) continue;
log.debug("found teacher id: {} -> {}"_f(params.Name, *teacherId));
// 抓取排班表在其中找到对应的时间段id
auto timeId = [&] -> std::optional<int>
{
auto res = get
(
"/api/mentality/scheduling/page/week/users",
{
{"campus", Campus[params.Campus].first},
{"type", Campus[params.Campus].second},
{"dateStart", params.Date},
{"dateEnd", params.Date}
}
);
if (!res) return {};
for (auto time : YAML::Load(*res)["data"])
if (time["timeQuantumStart"].as<std::string>() == params.Time)
return log.rtn(time["id"].as<int>());
log.error("time slot not found: {}"_f(params.Time));
return {};
}();
if (!timeId) continue;
log.debug("found time id: {} -> {}"_f(params.Time, *timeId));
// 提交增加排班的请求
auto body = [&]
{
nlohmann::json j;
j["campus"] = Campus[params.Campus].first;
j["type"] = Campus[params.Campus].second;
j["userId"] = *teacherId;
j["isVisual"] = true;
j["dayTimeIds"] = std::vector{*timeId};
return log.rtn(j.dump());
}();
auto res = post("/api/mentality/scheduling/teachers", body);
if (res) std::cout << *res << std::endl;
}
else log.error("unknown job type: {}"_f(job.Type));
}
return 0;
}