我的个人Flash收藏站首页装修完毕!


Flash收藏站

我的个人Flash收藏站首页装修完毕!顺带用C++写了俩RSS、站点地图生成器

首页图片:

页脚:

这是我搜刮的Flash游戏收藏站,今天装修了页面颜色和页脚,新颜色看着舒服多了

Flash收藏站

RSS订阅文件生成器:

此RSS订阅生成器是通过读取我预留的Json元信息生成的,新链接的时间为第一次运行时间,链接的时间会储存在日志中,xml的优先级大于日志,可以手动修改xml RSS订阅时间,手动修改xml中的时间会在下一次程序运行时被更新进日志。

Json格式为:

[
    {
      "name": "驾驶TU-95",
      "desc": "驾驶战略轰炸机TU-95!带有汉化"
    },
    {
      "name": "文具防御",
      "desc": "使用文具打击来犯之敌!带有汉化"
    }
]
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <set>
#include <vector>
#include <ctime>
#include <json.hpp>

using json = nlohmann::json;

// RFC-822 格式时间
std::string getCurrentTime() {
    std::time_t now = std::time(nullptr);
    char buf[80];
    std::strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", std::gmtime(&now));
    return std::string(buf);
}

std::string extractBetween(const std::string& str, const std::string& start_delim, const std::string& end_delim) {
    size_t start = str.find(start_delim);
    if (start == std::string::npos) return "";
    start += start_delim.size();
    size_t end = str.find(end_delim, start);
    if (end == std::string::npos) return "";
    return str.substr(start, end - start);
}

json readXmlPubDates(const std::string& xmlFilename) {
    json xmlMap = json::object();
    std::ifstream xmlFile(xmlFilename);
    if (!xmlFile.is_open())
        return xmlMap;

    std::string line;
    std::string currentLink;
    while (std::getline(xmlFile, line)) {
        if (line.find("<link>") != std::string::npos) {
            currentLink = extractBetween(line, "<link>", "</link>");
        } else if (line.find("<pubDate>") != std::string::npos) {
            std::string pubDate = extractBetween(line, "<pubDate>", "</pubDate>");
            if (!currentLink.empty()) {
                xmlMap[currentLink] = pubDate;
                currentLink.clear();
            }
        }
    }
    xmlFile.close();
    return xmlMap;
}

// 加载日志文件(日志是记录链接RSS时间的)
json loadLog(const std::string& logFilename) {
    json logData;
    std::ifstream logFile(logFilename);
    if (logFile.is_open()){
        try {
            logFile >> logData;
        } catch (json::parse_error& e) {
            std::cerr << "日志文件解析错误: " << e.what() << std::endl;
        }
        logFile.close();
    } else {
        logData = json::object();
    }
    return logData;
}

// 保存日志
void saveLog(const json& logData, const std::string& logFilename) {
    std::ofstream logFile(logFilename);
    if (logFile.is_open()){
        logFile << logData.dump(4);
        logFile.close();
    } else {
        std::cerr << "无法保存日志文件: " << logFilename << std::endl;
    }
}

#ifdef _WIN32
    #include <windows.h>
    #define timegm _mkgmtime
#endif

int main(int argc, char* argv[]) {
    std::string jsonInputFilename = "api/games_name.json";
    std::string xmlOutputFilename = "rss.xml";
    std::string logFilename = "rss_log.json";

    // --- 1. 读取 JSON  ---
    std::ifstream inputFile(jsonInputFilename);
    if (!inputFile.is_open()){
        std::cerr << "无法打开文件 " << jsonInputFilename << std::endl;
        return 1;
    }
    json jsonData;
    inputFile >> jsonData;
    inputFile.close();

    // --- 2. 加载日志 ---
    json logData = loadLog(logFilename);

    // --- 3. 尝试读取当前目录下的 rss.xml 中记录的时间(若已运行过) ---
    json xmlMap = readXmlPubDates(xmlOutputFilename);

    // 存储JSON链接
    std::set<std::string> jsonLinks;

    // --- 4. 生成 RSS XML 内容 ---
    std::ostringstream xmlContent;
    xmlContent << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
    xmlContent << "<rss version=\"2.0\">\n";
    xmlContent << "  <channel>\n";
    xmlContent << "    <title>Flash收藏站</title>\n";
    xmlContent << "    <link>https://flash.100713.xyz/</link>\n";
    xmlContent << "    <description>最新Flash游戏列表 RSS 订阅</description>\n";
    xmlContent << "    <language>zh-CN</language>\n";
    xmlContent << "    <lastBuildDate>" << getCurrentTime() << "</lastBuildDate>\n";

    for (const auto& item : jsonData) {
        std::string name = item["name"];
        std::string desc = item["desc"];
        std::string link = "https://flash.100713.xyz/" + name;
        jsonLinks.insert(link);

        std::string pubDate;
        if (item.contains("pubDate")) {
            pubDate = item["pubDate"];
        } else if (xmlMap.contains(link)) {
            pubDate = xmlMap[link];
        } else if (logData.contains(link)) {
            pubDate = logData[link];
        } else {
            pubDate = getCurrentTime();
        }

        if (!logData.contains(link) || logData[link] != pubDate) {
            logData[link] = pubDate;
        }

        xmlContent << "    <item>\n";
        xmlContent << "      <title>" << name << "</title>\n";
        xmlContent << "      <link>" << link << "</link>\n";
        xmlContent << "      <description>" << desc << "</description>\n";
        xmlContent << "      <pubDate>" << pubDate << "</pubDate>\n";
        xmlContent << "    </item>\n";
    }

    std::vector<std::string> keysToRemove;
    for (auto it = logData.begin(); it != logData.end(); ++it) {
        const std::string& link = it.key();
        if (jsonLinks.find(link) == jsonLinks.end()) {
            keysToRemove.push_back(link);
        }
    }
    for (const auto& link : keysToRemove) {
        logData.erase(link);
    }

    xmlContent << "  </channel>\n";
    xmlContent << "</rss>\n";

    std::ofstream outputFile(xmlOutputFilename);
    if (!outputFile.is_open()){
        std::cerr << "无法创建文件 " << xmlOutputFilename << std::endl;
        return 1;
    }
    outputFile << xmlContent.str();
    outputFile.close();

    // --- 更新的日志 ---
    saveLog(logData, logFilename);

    if (argc > 1 && std::strcmp(argv[1], "-c") == 0) {
        std::cout << "RSS 订阅链接文件生成完毕" << xmlOutputFilename << std::endl;
    } else {
#ifdef _WIN32
        HWND consoleWnd = GetConsoleWindow();
        if (consoleWnd != NULL) {
            ShowWindow(consoleWnd, SW_HIDE);
        }
        MessageBoxW(NULL, L"RSS 订阅链接文件生成完毕", L"OK!", MB_OK);
#else
        std::cout << "RSS 订阅链接文件生成完毕" << xmlOutputFilename << std::endl;
#endif
    }

    return 0;
}

站点地图生成器:

此站点地图生成器是通过读取RSS订阅文件来获取链接、链接标题、时间的.

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include "json.hpp"
#include <ctime>
#include <iomanip>
#include <cstring>

#ifdef _WIN32
    #include <windows.h>
    #define timegm _mkgmtime
#endif

using json = nlohmann::json;

std::string convertToSitemapTime(const std::string &rssTime) {
    std::tm tm = {};
    std::istringstream iss(rssTime);
    iss >> std::get_time(&tm, "%a, %d %b %Y %H:%M:%S GMT");
    if (iss.fail()) {
        std::cerr << "时间格式解析失败: " << rssTime << std::endl;
        return "";
    }
    time_t t = timegm(&tm);
    std::tm* gmt = std::gmtime(&t);
    
    char buf[80];
    std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S+00:00", gmt);
    return std::string(buf);
}

std::string extractTitleFromUrl(const std::string &url) {
    size_t pos = url.find_last_of('/');
    if (pos == std::string::npos || pos + 1 >= url.size())
        return url;
    return url.substr(pos + 1);
}

int main(int argc, char* argv[]) {
    std::setlocale(LC_ALL, "");
    
    // 读取日志文件前面RSS订阅文件生成器的日志
    std::string logFilename = "rss_log.json";
    std::ifstream logFile(logFilename);
    if (!logFile.is_open()) {
        std::cerr << "无法打开日志文件: " << logFilename << std::endl;
        return 1;
    }
    
    json logData;
    try {
        logFile >> logData;
    } catch (json::parse_error &e) {
        std::cerr << "日志文件解析错误: " << e.what() << std::endl;
        return 1;
    }
    logFile.close();
    
    // 生成 sitemap.xml
    std::ofstream sitemapFile("sitemap.xml");
    if (!sitemapFile.is_open()) {
        std::cerr << "无法创建 sitemap.xml 文件" << std::endl;
        return 1;
    }
    
    sitemapFile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
    sitemapFile << "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n";
    
    for (auto it = logData.begin(); it != logData.end(); ++it) {
        std::string url = it.key();
        std::string rssTime = it.value(); 
        std::string sitemapTime = convertToSitemapTime(rssTime);
        std::string title = extractTitleFromUrl(url);
        
        sitemapFile << "  <url>\n";
        sitemapFile << "    <loc>" << url << "</loc>\n";
        sitemapFile << "    <lastmod>" << sitemapTime << "</lastmod>\n";
        sitemapFile << "    <title>" << title << "</title>\n";
        sitemapFile << "  </url>\n";
    }
    sitemapFile << "</urlset>\n";
    sitemapFile.close();
    
    if (argc > 1 && std::strcmp(argv[1], "-c") == 0) {
        std::cout << "站点地图生成完毕" << std::endl;
    } else {
#ifdef _WIN32
        HWND consoleWnd = GetConsoleWindow();
        if (consoleWnd != NULL) {
            ShowWindow(consoleWnd, SW_HIDE);
        }
        
        MessageBoxW(NULL, L"站点地图生成完毕", L"OK!", MB_OK);
#else
        std::cout << "站点地图生成完毕" << std::endl;
#endif
    }
    
    return 0;
}


  目录