◕小莫◕ 发表于 2020-8-10 14:28

【备忘】C++链接Mod站实现自动检查版本更新


想要使用Mod站的API,需要在发布Mod之前,勾选“启用API”


然后即可在Mod页面的左上角看到“API”按钮(仅作者可见)


点击即可打开API页面(如https://mod.blacksheepgame.com/mod/API/147160),查看当前Mod的json数据,要检查更新,只需要判断“mods_version”参数即可(当然,你也可以判断别的参数)

以C++为例,我解析json使用的库是:https://github.com/nlohmann/json

先引用需要用到的资源
#include <atlstr.h>
#include <wininet.h>
#pragmacomment(lib, "wininet.lib")

#include "json/json.hpp"

#include <sstream>
#include <iomanip>
using json = nlohmann::json;


读取网页数据:
//对网页进行转码
wchar_t* Convert(CString str, int targetCodePage)
{

      int iunicodeLen = MultiByteToWideChar(targetCodePage, 0, (LPCTSTR)str.GetBuffer(), -1, NULL, 0);
      wchar_t* pUnicode = NULL;
      pUnicode = new wchar_t;
      memset(pUnicode, 0, (iunicodeLen + 1) * sizeof(wchar_t));
      MultiByteToWideChar(targetCodePage, 0, (LPCTSTR)str.GetBuffer(), -1, (LPWSTR)pUnicode, iunicodeLen);//映射一个字符串到一个款字节中
      return pUnicode;
}

/*获取网页的源码,参数1为网页链接,2为缓冲区指针*/
bool GetHtml(LPCTSTR szURL, CString& getbuf)
{
      HINTERNET      hInternet, hUrl;
      char                buffer;
      WCHAR                wBuffer;

      DWORD                dwBytesRead = 0;
      DWORD                dwBytesWritten = 0;
      BOOL                bIsFirstPacket = true;
      BOOL                bRet = true;
      int                        nNowcopyDate = 0;

      hInternet = InternetOpen(_T("Mozilla/4.0 (compatible)"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, INTERNET_INVALID_PORT_NUMBER, 0);//初始化应用程序,使用WinNet
      if (hInternet == NULL)
                return FALSE;

      hUrl = InternetOpenUrl(hInternet, szURL, NULL, 0, INTERNET_FLAG_RELOAD, 0);//打开一个资源 ftp,gopher,http开头

      if (hUrl == NULL)
      {
                DWORD m = GetLastError();
                return FALSE;
      }
      do
      {
                memset(buffer, 0, sizeof(char) * 1124);
                InternetReadFile(hUrl, buffer, sizeof(char) * 1024, &dwBytesRead);
                bIsFirstPacket = false;
                nNowcopyDate = +dwBytesRead;
                wchar_t* punicode;
                punicode = Convert(buffer, CP_UTF8);// 对源码进行转码   第二个参数为网页的编码格式
               
                //CString strTmp = CString(buffer);      

                getbuf += _T("\r\n");
                getbuf += punicode;
                delete punicode;
      } while (dwBytesRead > 0);

      InternetCloseHandle(hUrl);
      InternetCloseHandle(hInternet);
      return TRUE;
}


检查更新:
//检测更新
string CheckUpdates()
{
      double nowV = 0.901;      //当前版本
      std::stringstream str;
      str << std::setprecision(3) << nowV;
      string v = "当前版本 " + str.str() + " ";                //显示内容
      try
      {
                json js;
                CStringretbuf;
                if (GetHtml(TEXT("https://mod.blacksheepgame.com/mod/API/147160"), retbuf))      //是否成功读取,将值写入retbuf
                {
                        //retbuf值:
                        //{"id":"147160","mods_version":"0.81","mods_author":"◕小莫◕","mods_click_cnt":295451,"mods_download_cnt":90961,"mods_mark_cnt":37389,"mods_collection_cnt":19098,"mods_updateTime":"2020-03-29 15:39:57"}
                        js = json::parse((string)retbuf);                //str to json
                        string newVs = js["mods_version"];      //获取版本
                        float newVf = stof(newVs);                        //转为float
                        if (nowV < newVf)                                        //判断版本新旧
                        {
                              return GT(v +"[有新更新可用!]");
                        }
                        else {
                              return GT(v +"[已是最新版本]");
                        }
                }
                else
                {
                        return GT(v + "[无法检测更新]");
                }
      }
      catch (const std::exception&)
      {
                return GT(v + "[无法检测更新]");
      }
}

顺便提一下,GT()函数是我写的一个GBK 转UTF8的汉化,用来解决中文乱码的问题:
//GBK编码转换到UTF8编码
string GT(const string& strGBK)
{
        string strOutUTF8 = "";
        WCHAR* str1;
        int n = MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, NULL, 0);
        str1 = new WCHAR;
        MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, str1, n); n = WideCharToMultiByte(CP_UTF8, 0, str1, -1, NULL, 0, NULL, NULL);
        char* str2 = new char;
        WideCharToMultiByte(CP_UTF8, 0, str1, -1, str2, n, NULL, NULL);
        strOutUTF8 = str2;
        delete[]str1;
        str1 = NULL;
        delete[]str2;
        str2 = NULL;
        return strOutUTF8;
}


页: [1]
查看完整版本: 【备忘】C++链接Mod站实现自动检查版本更新