diff --git a/main.go b/main.go new file mode 100644 index 0000000..b8d90f0 --- /dev/null +++ b/main.go @@ -0,0 +1,216 @@ +/* +Copyright Ghink Network Studio +Website: https://www.ghink.net +*/ + +package main + +import ( + "net/http" + "log" + "strings" + "time" + "encoding/json" + "fmt" + "io/ioutil" + "os" + "io" + "crypto/sha256" + "encoding/hex" +) + +var WorkPath,DataPath string +var NodeList,Database,Dataread []map[string]string +var Loger *log.Logger +var ch chan bool + +func responseICON(w http.ResponseWriter,r *http.Request) { + w.Header().Set("Location","https://resource.ghink.net/public/img/logo/ghink.png") + w.WriteHeader(301) +} +func responseError(w http.ResponseWriter,r *http.Request,httpCode int,info string,errorCode int) { + w.Header().Set("Content-Type","application/json") + w.WriteHeader(httpCode) + type returnError struct{ + HttpCode int `json:"httpCode"` + Info string `json:"info"` + ErrorCode int `json:"errorCode"` + } + returnInfo:=returnError{httpCode,info,errorCode} + b,_:=json.Marshal(returnInfo) + w.Write(b) +} +func responseWiKi(w http.ResponseWriter,r *http.Request) { + w.Header().Set("Content-Type","application/json") + w.WriteHeader(200) + type returnWiki struct{ + HttpCode int `json:"httpCode"` + Wiki string `json:"wiki"` + } + returnInfo:=returnWiki{200,"https://gitee.com/ghink/gmclapi/wikis"} + b,_:=json.Marshal(returnInfo) + w.Write(b) +} +func responseFile(w http.ResponseWriter,r *http.Request,value []string) { + path:=DataPath + for _,arg := range value{ + path=path+"/"+arg + } + if path==""{ + responseError(w,r,403,"Directory listing is not allowed",10002) + }else{ + b,err:=ioutil.ReadFile(path) + if err != nil { + if find := strings.Contains(err.Error(),"The system cannot find"); find{ + responseError(w,r,404,"Cannot find file",10003) + }else if s,_:=os.Stat(path); s.IsDir(){ + responseError(w,r,403,"Directory listing is not allowed",10002) + }else{ + responseError(w,r,500,"The file exists but cannot be read",10004) + logIn("[Page Thread]","Read the file ",path," failed in data dir! Error info: ",err.Error()) + } + }else{ + w.Write(b) + } + } +} +func pageService(w http.ResponseWriter,r *http.Request) { + ts := time.Now().Unix() + logIn("[Page Thread]","Got requests from ",r.RemoteAddr,", address is ",r.URL.RequestURI()) + w.Header().Set("Server","GMCLAPI (Alpha 1.0.0)") + w.Header().Set("Engine","Panda (Alpha 1.0.0)") + w.Header().Set("Stamp",fmt.Sprint(ts)) + addr:=r.URL.RequestURI() + value:=strings.Split(addr,"/") + pathType:=value[1] + value=value[2:] + if addr=="/"{ + responseWiKi(w,r) + }else{ + switch pathType { + case "favicon.ico": + responseICON(w,r) + case "file": + responseFile(w,r,value) + /* + case "official": + responseOfficial(w,r,value) + case "bmclapi": + responseBMCLAPI(w,r,value) + case "default": + responseDefault(w,r,value) + case "gmclapi": + responseDefault(w,r,value) + */ + default: + responseError(w,r,405,"Unspported choice for requests loading",10001) + } + } +} +func databaseService() { + for { + file,err:=os.OpenFile(WorkPath+"/database.db",os.O_RDONLY,0600) + defer file.Close() + if err != nil { + panic(err) + } + bytes,err:=ioutil.ReadAll(file) + if err != nil { + panic(err) + } + err=json.Unmarshal(bytes,&Database) + if err != nil { + panic(err) + } + time.Sleep(time.Duration(10)*time.Second) + } +} +func nodeService() { + +} +func determineNode(file string) string { + return "http://127.0.0.1/file"+file +} +func syncService() { + for { + } +} +func hashFile(path string) string { + file,err:=os.Open(path) + defer file.Close() + if err != nil { + logIn("[Hash Thread]","Failed to calc hash of the file ",path,"! Error info: ",err.Error()) + } + hash:=sha256.New() + if _,err := io.Copy(hash,file); err != nil { + logIn("[Hash Thread]","Failed to calc hash of the file ",path,"! Error info: ",err.Error()) + } + sum:=hash.Sum(nil) + return hex.EncodeToString(sum) +} +func logIn(text ...string) { + result:="" + for _,arg := range text { + result+=arg + } + log.Print(result) + Loger.Print(result) +} +func init() { + WorkPath="gmclapi/" + DataPath=WorkPath+"data/" + err:=os.MkdirAll(WorkPath, os.ModePerm) + if err != nil { + panic(err) + } + err=os.MkdirAll(DataPath, os.ModePerm) + if err != nil { + panic(err) + } + if _,err:=os.Stat(WorkPath+"database.db"); os.IsNotExist(err){ + database,err:=os.OpenFile(WorkPath+"database.db", os.O_WRONLY|os.O_CREATE, 0666) + database.Write([]byte("[]")) + if err != nil { + panic(err) + } + defer database.Close() + } + file,err:=os.OpenFile(WorkPath+"/database.db", os.O_RDONLY,0600) + defer file.Close() + if err != nil { + panic(err) + } + bytes,err:=ioutil.ReadAll(file) + if err != nil { + panic(err) + } + err=json.Unmarshal(bytes,&Database) + if err != nil { + panic(err) + } +} +func main() { + logFile,err:=os.OpenFile(WorkPath+"logs.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + panic(err) + } + defer logFile.Close() + Loger=log.New(logFile,"",log.LstdFlags|log.Lshortfile) + http.HandleFunc("/", pageService) + go http.ListenAndServe("127.0.0.1:8000", nil) + go syncService() + go databaseService() + /* + go nodeService() + go consoleService() + */ + for { + + } +} +/* +10001 Unspported choice for requests loading +10002 Directory listing is not allowed +10003 Cannot find file +10004 The file exists but cannot be read +*/ \ No newline at end of file diff --git a/mainServer.go b/mainServer.go deleted file mode 100644 index af4752c..0000000 --- a/mainServer.go +++ /dev/null @@ -1,8 +0,0 @@ -package main - -//mainServer for GMCL API. - -import ( - "net" - "log" -) \ No newline at end of file diff --git a/subDownloadServer.go b/subDownloadServer.go deleted file mode 100644 index a3e1c95..0000000 --- a/subDownloadServer.go +++ /dev/null @@ -1,8 +0,0 @@ -package main - -//subDownloadServer for GMCL API. - -import ( - "net" - "log" -) \ No newline at end of file diff --git a/subRequestServer.go b/subRequestServer.go deleted file mode 100644 index 1c7ce90..0000000 --- a/subRequestServer.go +++ /dev/null @@ -1,8 +0,0 @@ -package main - -//subRequestServer for GMCL API. - -import ( - "net" - "log" -) \ No newline at end of file diff --git a/sync.py b/sync.py new file mode 100644 index 0000000..212fad3 --- /dev/null +++ b/sync.py @@ -0,0 +1,97 @@ +''' +Copyright Ghink Network Studio +Website: https://www.ghink.net +''' +import requests,os,time,json,threading,hashlib,re +from urllib.parse import urlparse + +db=[] +workPath="gmclapi/" +dataPath=workPath+"data/" +userAgent={'User-Agent':'GMCLAPI/0.0.1'} +proxies = { + "http": "http://127.0.0.1:4780" +} +entrance=["http://launchermeta.mojang.com/mc/game/version_manifest.json"] + +def log(info): + info="{}{}".format(time.strftime("%Y/%m/%d %H:%M:%S [Sync Thread]", time.localtime()),info) + print(info) + with open(workPath+"logs.log","a+") as fb: + fb.write(info) + fb.write("\r\n") +def database(): + global db + with open(workPath+"database.db","r") as fb: + db=json.loads(fb.read()) + while True: + with open(workPath+"database.db","r") as fb: + if json.loads(fb.read())==db: + continue + with open(workPath+"database.db","w+") as fb: + fb.write(json.dumps(db)) +def syncMain(): + global entrance + global userAgent + global proxies + for obj in entrance: + origin=requests.get(obj,headers=userAgent,proxies=proxies).content + md5=hashlib.md5() + md5.update(origin) + hash=md5.hexdigest() + switch=True + for h in db: + if h["hash"]==hash: + switch=False + break + if switch: + i=0 + for h in db: + if h["path"]==urlparse(obj).path: + del switch[i] + i+=1 + with open(dataPath+hash,"wb") as fb: + fb.write(origin) + db.append({ + "hash":hash, + "source":obj, + "path":urlparse(obj).path + }) +def syncMinecraft(): + global userAgent + global proxies + for h in db: + if h["path"]=="/mc/game/version_manifest.json": + hash=h["hash"] + break + with open(dataPath+hash,"r") as fb: + fall=fb.read() + result=re.findall('(https?|ftp|file)|([-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|])',fall) + print(result) + res=[] + for i in result: + res.append("{}{}".format(i[0]+i[1])) + for obj in res: + switch=True + for h in db: + if h["source"]==obj: + switch=False + if switch: + origin=requests.get(obj,headers=userAgent,proxies=proxies).content + md5=hashlib.md5() + md5.update(origin) + hash=md5.hexdigest() + with open(dataPath+hash,"wb") as fb: + fb.write(origin) + db.append({ + "hash":hash, + "source":obj, + "path":urlparse(obj).path + }) +def main(): + threading.Thread(target=database).start() + syncMain() +#main() +threading.Thread(target=database).start() +time.sleep(1) +syncMinecraft() \ No newline at end of file