// 磁力链转种子 func (this *IndexController) Torrent() { if this.Ctx.Request.Method == "POST" { // 获取磁力链接 magnet := this.GetString("magnetLink") // 将磁力链接转换为大写格式 magnet = strings.ToUpper(magnet) // 定义一个正则 re, _ := regexp.Compile(`MAGNET:\?XT=URN:BTIH:([^&]+)`) // 匹配磁力链接 match := re.FindAllString(magnet, -1) // 获取infohash magnet = strings.Replace(match[0], "MAGNET:?XT=URN:BTIH:", "", -1) // 去除空格并转换为大写 magnet = strings.ToUpper(strings.TrimSpace(magnet)) if match[0] == "" { // 如果匹配不到磁力链接 if len(magnet) != 40 { // 跳转404 this.Abort("404") } } // 检测infohash是否已经存在 if !models.Has(models.DbHash, bson.M{"infohash": magnet}) { // 定义一个SC_Hash var schash models.SC_Hash // 设置SC_Hash schash.Hot = 1 schash.IsPut = true schash.InfoHash = magnet // 保存hash数据 err := schash.Save() if err == nil { // 自增统计数据 models.SaveLog(time.Now().Format("20060102"), "dhtnums") } } // 检测infohash是否已入库过 if !models.Has(models.DbInfo, bson.M{"infohash": magnet}) { // 下载并入库种子 ret, err := common.PullTorrent(magnet) if err != nil || ret != 0 { this.Abort("404") } } // 跳转到种子信息页 this.Redirect("/"+magnet, 302) } this.TplNames = "torrent.html" }
// 输出Hash func OutHash(master chan string) { for { select { case infohash := <-master: if models.DbConfig.ShowMsg { fmt.Println("Get InfoHash: ", infohash) } // 定义一个SC_Hash var schash models.SC_Hash // 设置SC_Hash schash.Hot = 1 schash.IsPut = false schash.InfoHash = strings.ToUpper(strings.TrimSpace(infohash)) // 检测infohash是否存在 has := models.Has(models.DbHash, bson.M{"infohash": schash.InfoHash}) // 保存hash数据 err := schash.Save() if err == nil && has == false { // 自增统计数据 models.SaveLog(time.Now().Format("20060102"), "dhtnums") } // 修改种子热度 models.SetHot(schash.InfoHash) } } }
// 种子入库 func PutTorrent(metaTorrent MetaInfo) error { // 定义一个SC_Info var scinfo models.SC_Info // 如果有utf-8格式名称 if metaTorrent.Info.Name8 != "" { // 直接使用utf-8格式的 scinfo.Caption = strings.TrimSpace(metaTorrent.Info.Name8) } else { // 否则使用非utf-8格式 scinfo.Caption = strings.TrimSpace(metaTorrent.Info.Name) } // 设置infohash, 并转换为大写格式 scinfo.InfoHash = strings.ToUpper(metaTorrent.InfoHash) // 如果没有获取到creationdate信息 if metaTorrent.CreationDate == 0 { // 将creationdate设置为当前时间 scinfo.CreateTime = time.Now() } else { // 否则为获取到的时间 scinfo.CreateTime = time.Unix(metaTorrent.CreationDate, 0) } // 定义一个File var file File // 定义一个File列表保存路径信息 var spath []File // 判断文件列表是否大于0 if len(metaTorrent.Info.Files) > 0 { // 循环处理文件列表 for _, FileDict := range metaTorrent.Info.Files { // 加上文件长度 scinfo.Length += FileDict.Length // 文件数量+1 scinfo.FileCount += 1 // 设置文件长度 file.Length = FileDict.Length // 清空文件路径 file.Path = "" if FileDict.Path8 != nil { // 如果存在utf8编码则使用utf8编码 for _, path := range FileDict.Path8 { file.Path += strings.TrimSpace(path) + "/" } } else { // 否则使用默认 for _, path := range FileDict.Path { file.Path += strings.TrimSpace(path) + "/" } } // 获取最后一个/的位置 index := strings.LastIndex(file.Path, "/") if index <= len(file.Path) && index != -1 { // 将最后一个/去掉 file.Path = file.Path[0:index] } // 将文件信息加入列表 scinfo.Files = append(scinfo.Files, file) // 加入路径信息 spath = append(spath, file) } } else { // 设置文件长度 scinfo.Length = metaTorrent.Info.Length // 设置文件数量 scinfo.FileCount = 1 // 设置文件路径 file.Path = scinfo.Caption // 设置文件长度 file.Length = scinfo.Length // 将文件本身加入列表 scinfo.Files = append(scinfo.Files, file) // 加入路径信息 spath = append(spath, file) } // 对路径数组循环 for _, f := range spath { // 分割路径 p := strings.Split(f.Path, "/") // 创建树结构 treeDir(p, f.Length) } // 设置树结构 scinfo.FileList = append(scinfo.FileList, root) // 清空 root.Dirs = nil root.Files = nil // 设置文件热度为1 scinfo.Hot = 1 // 如果都没有问题 if scinfo.Caption != "" && scinfo.FileCount > 0 && scinfo.InfoHash != "" { // 定义一个正则 re, _ := regexp.Compile("\\pP|\\pS") // 去除种子名称中的所有符号 caption := re.ReplaceAllString(scinfo.Caption, " ") // 检测是否存在 if !models.Has(models.DbInfo, bson.M{"infohash": scinfo.InfoHash}) { // 设置种子分词 scinfo.Keys = Sego(caption) // 设置种子发布时间 scinfo.PutTime = time.Now() // 保存种子信息 err := scinfo.Save() if err == nil { // 设置当前hash已经入库 models.SetPut(scinfo.InfoHash) // 自增统计数据 models.SaveLog(time.Now().Format("20060102"), "putnums") // 定义一个Qrcode对象 qr := &Qrcode{ Version: 0, Level: ECLevelM, ModuleSize: 7, QuietZoneWidth: 0, } // 生成二维码 img, _ := qr.Encode("magnet:?xt=urn:btih:" + scinfo.InfoHash) // 截取infohash作为目录 dir := "./static/qrcode/" + scinfo.InfoHash[0:1] + "/" + scinfo.InfoHash[1:2] + "/" + scinfo.InfoHash[2:3] + "/" + scinfo.InfoHash[3:4] + "/" + scinfo.InfoHash[4:5] + "/" + scinfo.InfoHash[5:6] + "/" + scinfo.InfoHash[6:7] // 创建目录 os.MkdirAll(dir, 0777) // 创建二维码图片文件 f, _ := os.Create(fmt.Sprintf("%s/%s.png", dir, scinfo.InfoHash)) // 保证正确关闭 defer f.Close() // 将二维码写入文件 png.Encode(f, img) } return err } else { // 如果没有设置为入库 if !models.IsPut(scinfo.InfoHash) { // 设置为入库 return models.SetPut(scinfo.InfoHash) } } } return nil }
// 种子转磁力链 func (this *IndexController) Magnet() { if this.Ctx.Request.Method == "POST" { // 获取上传文件 f, h, err := this.GetFile("torrentFile") if err != nil { // 跳转404 this.Abort("404") } // 保证正确关闭 defer f.Close() // 获取最后一个.出现的位置 index := strings.LastIndex(h.Filename, ".") // 获取文件后缀 ext := strings.ToUpper(h.Filename[index+1:]) // 若不是种子文件后缀则报错 if ext != "TORRENT" { // 跳转404 this.Abort("404") } // 读取种子信息 meta, err := common.ReadTorrent(f) if err != nil || len(meta.InfoHash) != 40 { // 跳转404 this.Abort("404") } // 获取种子UTF-8格式名称 caption := meta.Info.Name8 if caption == "" { // 获取失败则获取默认名称 caption = meta.Info.Name } // 种子入库 err = common.PutTorrent(meta) if err == nil { // 检测infohash是否已经存在 if models.Has(models.DbHash, bson.M{"infohash": strings.ToUpper(strings.TrimSpace(meta.InfoHash))}) { // 设置当前infohash已经入库 models.SetPut(strings.ToUpper(strings.TrimSpace(meta.InfoHash))) } else { // 定义一个SC_Hash var schash models.SC_Hash // 设置SC_Hash schash.Hot = 1 schash.IsPut = true schash.InfoHash = strings.ToUpper(strings.TrimSpace(meta.InfoHash)) // 保存hash数据 err = schash.Save() if err == nil { // 自增统计数据 models.SaveLog(time.Now().Format("20060102"), "dhtnums") } } this.Redirect("/"+strings.ToUpper(strings.TrimSpace(meta.InfoHash)), 302) } } this.TplNames = "magnet.html" }
// 入库主函数 func Put() { // 设置最大允许使用CPU核心数 runtime.GOMAXPROCS(2) // 定义一个通道 chReq := make(chan models.SC_Hash, 10) // 定义一个通道 chRes := make(chan string, 10) // 无限循环入库种子 for { // 获取未入库hash总量 allcount := models.Count(models.DbHash, bson.M{"isput": false, "invalid": bson.M{"$lte": 3}}) // 如果数量小于1 if allcount < 1 { // 停顿10秒 time.Sleep(10 * time.Second) // 跳过本次循环 continue } for ai := 0; ai < allcount; { // 定义一个SC_Hash列表 var sc_hash []models.SC_Hash // 获取100条infohash models.GetDataByQuery(models.DbHash, ai, (ai + 100), "-hot", bson.M{"isput": false, "invalid": bson.M{"$lte": 3}}, &sc_hash) // 获取到的总量 count := len(sc_hash) // 循环处理infohash, 每次处理进程为自定义进程数 for i := 0; i < 10; i++ { go func() { // 循环处理 for { // 循环接受通道传递过来的infohash schash := <-chReq // 检查infohash是否已经入库 if models.Has(models.DbInfo, bson.M{"infohash": strings.ToUpper(schash.InfoHash)}) { // 入库则输出跳过信息 chRes <- fmt.Sprintf("'%s' Skip......", schash.InfoHash) // 将hash设置为已入库 models.SetPut(schash.InfoHash) // 跳过本次循环 continue } // 定义一个string变量, 记录处理结果 var str string // 入库种子信息 ret, err := PullTorrent(schash.InfoHash) if err == nil && ret == 0 { // 设置成功信息 str = fmt.Sprintf("Storage InfoHash '%s' Success......", schash.InfoHash) } else { // 设置失败信息 str = fmt.Sprintf("Can not download '%s' torrent file......", schash.InfoHash) } // 传递处理结果 chRes <- str } }() } go func() { // 定义一个hashs列表 hashs := make([]models.SC_Hash, count) // 循环将infohash加入hashs列表 for i := 0; i < count; i++ { hashs[i] = sc_hash[i] } // 传递infohash给通道 for i := 0; i < count; i++ { chReq <- hashs[i] } }() // 循环处理入库结果 for i := 0; i < count; i++ { // 接收入库结果 str := <-chRes // 如果允许显示则显示 if models.DbConfig.ShowMsg && str != "" { fmt.Println(str) } else { // 否则不显示 _ = str } } } } }