This commit is contained in:
mubai
2023-12-23 22:32:52 +08:00
parent d85dbe915c
commit b48e53a637
151 changed files with 12451 additions and 1382 deletions

View File

@@ -0,0 +1,283 @@
package conver
import (
"encoding/xml"
"log"
"server/config"
"server/model/collect"
"server/model/system"
"strings"
)
/*
处理 不同结构体数据之间的转化
统一转化为内部结构体
*/
// GenCategoryTree 解析处理 filmListPage数据 生成分类树形数据
func GenCategoryTree(list []collect.FilmClass) *system.CategoryTree {
// 遍历所有分类进行树形结构组装
tree := &system.CategoryTree{Category: &system.Category{Id: 0, Pid: -1, Name: "分类信息", Show: true}}
temp := make(map[int64]*system.CategoryTree)
temp[tree.Id] = tree
for _, c := range list {
// 判断当前节点ID是否存在于 temp中
category, ok := temp[c.TypeID]
if ok {
// 将当前节点信息保存
category.Category = &system.Category{Id: c.TypeID, Pid: c.TypePid, Name: c.TypeName, Show: true}
} else {
// 如果不存在则将当前分类存放到 temp中
category = &system.CategoryTree{Category: &system.Category{Id: c.TypeID, Pid: c.TypePid, Name: c.TypeName, Show: true}}
temp[c.TypeID] = category
}
// 根据 pid获取父节点信息
parent, ok := temp[category.Pid]
if !ok {
// 如果不存在父节点存在, 则将父节点存放到temp中
temp[c.TypePid] = parent
}
// 将当前节点存放到父节点的Children中
parent.Children = append(parent.Children, category)
}
return tree
}
// ConvertCategoryList 将分类树形数据转化为list类型
func ConvertCategoryList(tree system.CategoryTree) []system.Category {
var cl = []system.Category{system.Category{Id: tree.Id, Pid: tree.Pid, Name: tree.Name, Show: tree.Show}}
for _, c := range tree.Children {
cl = append(cl, system.Category{Id: c.Id, Pid: c.Pid, Name: c.Name, Show: c.Show})
if c.Children != nil && len(c.Children) > 0 {
for _, subC := range c.Children {
cl = append(cl, system.Category{Id: subC.Id, Pid: subC.Pid, Name: subC.Name, Show: subC.Show})
}
}
}
return cl
}
// ConvertFilmDetails 批量处理影片详情信息
func ConvertFilmDetails(details []collect.FilmDetail) []system.MovieDetail {
var dl []system.MovieDetail
for _, d := range details {
dl = append(dl, ConvertFilmDetail(d))
}
return dl
}
// ConvertFilmDetail 将影片详情数据处理转化为 system.MovieDetail
func ConvertFilmDetail(detail collect.FilmDetail) system.MovieDetail {
md := system.MovieDetail{
Id: detail.VodID,
Cid: detail.TypeID,
Pid: detail.TypeID1,
Name: detail.VodName,
Picture: detail.VodPic,
DownFrom: detail.VodDownFrom,
MovieDescriptor: system.MovieDescriptor{
SubTitle: detail.VodSub,
CName: detail.TypeName,
EnName: detail.VodEn,
Initial: detail.VodLetter,
ClassTag: detail.VodClass,
Actor: detail.VodActor,
Director: detail.VodDirector,
Writer: detail.VodWriter,
Blurb: detail.VodBlurb,
Remarks: detail.VodRemarks,
ReleaseDate: detail.VodPubDate,
Area: detail.VodArea,
Language: detail.VodLang,
Year: detail.VodYear,
State: detail.VodState,
UpdateTime: detail.VodTime,
AddTime: detail.VodTimeAdd,
DbId: detail.VodDouBanID,
DbScore: detail.VodDouBanScore,
Hits: detail.VodHits,
Content: detail.VodContent,
},
}
// 通过分割符切分播放源信息 PlaySeparator $$$
md.PlayFrom = strings.Split(detail.VodPlayFrom, detail.VodPlayNote)
// v2 只保留m3u8播放源
md.PlayList = GenFilmPlayList(detail.VodPlayURL, detail.VodPlayNote)
md.DownloadList = GenFilmPlayList(detail.VodDownURL, detail.VodPlayNote)
return md
}
// GenFilmPlayList 处理影片播放地址数据, 只保留m3u8与mp4格式的链接,生成playList
func GenFilmPlayList(playUrl, separator string) [][]system.MovieUrlInfo {
var res [][]system.MovieUrlInfo
if separator != "" {
// 1. 通过分隔符切分播放源地址
for _, l := range strings.Split(playUrl, separator) {
// 2.只对m3u8播放源 和 .mp4下载地址进行处理
if strings.Contains(l, ".m3u8") || strings.Contains(l, ".mp4") {
// 2. 将每组播放源对应的播放列表信息存储到列表中
res = append(res, ConvertPlayUrl(l))
}
}
} else {
// 1.只对m3u8播放源 和 .mp4下载地址进行处理
if strings.Contains(playUrl, ".m3u8") || strings.Contains(playUrl, ".mp4") {
// 2. 将每组播放源对应的播放列表信息存储到列表中
res = append(res, ConvertPlayUrl(playUrl))
}
}
return res
}
// GenAllFilmPlayList 处理影片播放地址数据, 保留全部播放链接,生成playList
func GenAllFilmPlayList(playUrl, separator string) [][]system.MovieUrlInfo {
var res [][]system.MovieUrlInfo
if separator != "" {
// 1. 通过分隔符切分播放源地址
for _, l := range strings.Split(playUrl, separator) {
// 将playUrl中的所有播放格式链接均进行转换保存
res = append(res, ConvertPlayUrl(l))
}
return res
}
// 将playUrl中的所有播放格式链接均进行转换保存
res = append(res, ConvertPlayUrl(playUrl))
return res
}
// ConvertPlayUrl 将单个playFrom的播放地址字符串处理成列表形式
func ConvertPlayUrl(playUrl string) []system.MovieUrlInfo {
// 对每个片源的集数和播放地址进行分割 Episode$Link#Episode$Link
var l []system.MovieUrlInfo
for _, p := range strings.Split(playUrl, "#") {
// 处理 Episode$Link 形式的播放信息
if strings.Contains(p, "$") {
l = append(l, system.MovieUrlInfo{
Episode: strings.Split(p, "$")[0],
Link: strings.Split(p, "$")[1],
})
} else {
l = append(l, system.MovieUrlInfo{
Episode: "(`・ω・´)",
Link: p,
})
}
}
return l
}
// ConvertVirtualPicture 将影片详情信息转化为虚拟图片信息
func ConvertVirtualPicture(details []system.MovieDetail) []system.VirtualPicture {
var l []system.VirtualPicture
for _, d := range details {
if len(d.Picture) > 0 {
l = append(l, system.VirtualPicture{Id: d.Id, Link: d.Picture})
}
}
return l
}
// ----------------------------------Provide API---------------------------------------------------
// DetailCovertList 将影视详情信息转化为列表信息
func DetailCovertList(details []collect.FilmDetail) []collect.FilmList {
var l []collect.FilmList
for _, d := range details {
fl := collect.FilmList{
VodID: d.VodID,
VodName: d.VodName,
TypeID: d.TypeID,
TypeName: d.TypeName,
VodEn: d.VodEn,
VodTime: d.VodTime,
VodRemarks: d.VodRemarks,
VodPlayFrom: d.VodPlayFrom,
}
l = append(l, fl)
}
return l
}
// DetailCovertXml 将影片详情信息转化为Xml格式的对象
func DetailCovertXml(details []collect.FilmDetail) []collect.VideoDetail {
var vl []collect.VideoDetail
for _, d := range details {
vl = append(vl, collect.VideoDetail{
Last: d.VodTime,
ID: d.VodID,
Tid: d.TypeID,
Name: collect.CDATA{Text: d.VodName},
Type: d.TypeName,
Pic: d.VodPic,
Lang: d.VodLang,
Area: d.VodArea,
Year: d.VodYear,
State: d.VodState,
Note: collect.CDATA{Text: d.VodRemarks},
Actor: collect.CDATA{Text: d.VodActor},
Director: collect.CDATA{Text: d.VodDirector},
DL: collect.DL{DD: []collect.DD{collect.DD{Flag: d.VodPlayFrom, Value: d.VodPlayURL}}},
Des: collect.CDATA{Text: d.VodContent},
})
}
return vl
}
// DetailCovertListXml 将影片详情信息转化为Xml格式FilmList的对象
func DetailCovertListXml(details []collect.FilmDetail) []collect.VideoList {
var vl []collect.VideoList
for _, d := range details {
vl = append(vl, collect.VideoList{
Last: d.VodTime,
ID: d.VodID,
Tid: d.TypeID,
Name: collect.CDATA{Text: d.VodName},
Type: d.TypeName,
Dt: d.VodPlayFrom,
Note: collect.CDATA{Text: d.VodRemarks},
})
}
s, _ := xml.Marshal(vl[0])
log.Println(string(s))
return vl
}
// ClassListCovertXml 将影片分类列表转化为XML格式
func ClassListCovertXml(cl []collect.FilmClass) collect.ClassXL {
var l collect.ClassXL
for _, c := range cl {
l.ClassX = append(l.ClassX, collect.ClassX{ID: c.TypeID, Value: c.TypeName})
}
return l
}
// FilterFilmDetail 对影片详情数据进行处理, t 修饰类型 0-返回m3u8,mp4 | 1 返回 云播链接 | 2 返回全部
func FilterFilmDetail(fd collect.FilmDetail, t int64) collect.FilmDetail {
// 只保留 mu38 | mp4 格式的播放源, 如果包含多种格式的播放数据
if strings.Contains(fd.VodPlayURL, fd.VodPlayNote) {
switch t {
case 2:
fd.VodPlayFrom = config.PlayFormAll
case 1, 0:
for _, v := range strings.Split(fd.VodPlayURL, fd.VodPlayNote) {
if t == 0 && (strings.Contains(v, ".m3u8") || strings.Contains(v, ".mp4")) {
fd.VodPlayFrom = config.PlayForm
fd.VodPlayURL = v
} else if t == 1 && !strings.Contains(v, ".m3u8") && !strings.Contains(v, ".mp4") {
fd.VodPlayFrom = config.PlayFormCloud
fd.VodPlayURL = v
}
}
}
} else {
// 如果只有一种类型的播放链,则默认为m3u8 修改 VodPlayFrom 信息
fd.VodPlayFrom = config.PlayForm
}
return fd
}

View File

@@ -0,0 +1,53 @@
package conver
import (
"server/model/system"
"time"
)
/*
系统内部对象想换转换
*/
// CovertFilmDetailVo 将 FilmDetailVo 转化为 MovieDetail
func CovertFilmDetailVo(fd system.FilmDetailVo) (system.MovieDetail, error) {
t, err := time.ParseInLocation(time.DateTime, fd.AddTime, time.Local)
md := system.MovieDetail{
Id: fd.Id,
Cid: fd.Cid,
Pid: fd.Pid,
Name: fd.Name,
Picture: fd.Picture,
DownFrom: fd.DownFrom,
MovieDescriptor: system.MovieDescriptor{
SubTitle: fd.SubTitle,
CName: fd.CName,
EnName: fd.EnName,
Initial: fd.Initial,
ClassTag: fd.ClassTag,
Actor: fd.Actor,
Director: fd.Director,
Writer: fd.Writer,
Blurb: fd.Content,
Remarks: fd.Remarks,
ReleaseDate: fd.ReleaseDate,
Area: fd.Area,
Language: fd.Language,
Year: fd.Year,
State: fd.State,
UpdateTime: fd.UpdateTime,
AddTime: t.Unix(),
DbId: fd.DbId,
DbScore: fd.DbScore,
Hits: fd.Hits,
Content: fd.Content,
},
}
// 通过分割符切分播放源信息 PlaySeparator $$$
//md.PlayFrom = strings.Split(fd.VodPlayFrom, fd.VodPlayNote)
// v2 只保留m3u8播放源
md.PlayList = GenFilmPlayList(fd.PlayLink, "$$$")
//md.DownloadList = GenFilmPlayList(fd.DownloadLink, fd.VodPlayNote)
return md, err
}

View File

@@ -1,16 +1,16 @@
package dp
import (
"server/model"
"server/model/system"
)
// =================Spider数据处理=======================
// CategoryTree 组装树形菜单
func CategoryTree(list []model.ClassInfo) *model.CategoryTree {
func CategoryTree(list []system.ClassInfo) *system.CategoryTree {
// 遍历所有分类进行树形结构组装
tree := &model.CategoryTree{Category: &model.Category{Id: 0, Pid: -1, Name: "分类信息"}}
temp := make(map[int64]*model.CategoryTree)
tree := &system.CategoryTree{Category: &system.Category{Id: 0, Pid: -1, Name: "分类信息"}}
temp := make(map[int64]*system.CategoryTree)
temp[tree.Id] = tree
for _, c := range list {
@@ -18,10 +18,10 @@ func CategoryTree(list []model.ClassInfo) *model.CategoryTree {
category, ok := temp[c.Id]
if ok {
// 将当前节点信息保存
category.Category = &model.Category{Id: c.Id, Pid: c.Pid, Name: c.Name}
category.Category = &system.Category{Id: c.Id, Pid: c.Pid, Name: c.Name}
} else {
// 如果不存在则将当前分类存放到 temp中
category = &model.CategoryTree{Category: &model.Category{Id: c.Id, Pid: c.Pid, Name: c.Name}}
category = &system.CategoryTree{Category: &system.Category{Id: c.Id, Pid: c.Pid, Name: c.Name}}
temp[c.Id] = category
}
// 根据 pid获取父节点信息

View File

@@ -1,15 +1,15 @@
package dp
import (
"server/model"
"server/model/system"
"strings"
)
// ProcessMovieListInfo 处理影片列表中的信息
func ProcessMovieListInfo(list []model.MovieInfo) []model.Movie {
var movies []model.Movie
func ProcessMovieListInfo(list []system.MovieInfo) []system.Movie {
var movies []system.Movie
for _, info := range list {
movies = append(movies, model.Movie{
movies = append(movies, system.Movie{
Id: info.Id,
Name: info.Name,
Cid: info.Cid,
@@ -24,8 +24,8 @@ func ProcessMovieListInfo(list []model.MovieInfo) []model.Movie {
}
// ProcessMovieDetailList 处理影片详情列表数据
func ProcessMovieDetailList(list []model.MovieDetailInfo) []model.MovieDetail {
var detailList []model.MovieDetail
func ProcessMovieDetailList(list []system.MovieDetailInfo) []system.MovieDetail {
var detailList []system.MovieDetail
for _, d := range list {
detailList = append(detailList, ProcessMovieDetail(d))
}
@@ -33,15 +33,15 @@ func ProcessMovieDetailList(list []model.MovieDetailInfo) []model.MovieDetail {
}
// ProcessMovieDetail 处理单个影片详情信息
func ProcessMovieDetail(detail model.MovieDetailInfo) model.MovieDetail {
md := model.MovieDetail{
func ProcessMovieDetail(detail system.MovieDetailInfo) system.MovieDetail {
md := system.MovieDetail{
Id: detail.Id,
Cid: detail.Cid,
Pid: detail.Pid,
Name: detail.Name,
Picture: detail.Pic,
DownFrom: detail.DownFrom,
MovieDescriptor: model.MovieDescriptor{
MovieDescriptor: system.MovieDescriptor{
SubTitle: detail.SubTitle,
CName: detail.CName,
EnName: detail.EnName,
@@ -74,21 +74,21 @@ func ProcessMovieDetail(detail model.MovieDetailInfo) model.MovieDetail {
}
// ProcessPlayInfo 处理影片播放数据信息
func ProcessPlayInfo(info, sparator string) [][]model.MovieUrlInfo {
var res [][]model.MovieUrlInfo
func ProcessPlayInfo(info, separator string) [][]system.MovieUrlInfo {
var res [][]system.MovieUrlInfo
// 1. 通过分隔符区分多个片源数据
for _, l := range strings.Split(info, sparator) {
for _, l := range strings.Split(info, separator) {
// 2.对每个片源的集数和播放地址进行分割
var item []model.MovieUrlInfo
var item []system.MovieUrlInfo
for _, p := range strings.Split(l, "#") {
// 3. 处理 Episode$Link 形式的播放信息
if strings.Contains(p, "$") {
item = append(item, model.MovieUrlInfo{
item = append(item, system.MovieUrlInfo{
Episode: strings.Split(p, "$")[0],
Link: strings.Split(p, "$")[1],
})
} else {
item = append(item, model.MovieUrlInfo{
item = append(item, system.MovieUrlInfo{
Episode: "O(∩_∩)O",
Link: p,
})
@@ -101,24 +101,24 @@ func ProcessPlayInfo(info, sparator string) [][]model.MovieUrlInfo {
}
// ProcessPlayInfoV2 处理影片信息方案二 只保留m3u8播放源
func ProcessPlayInfoV2(info, sparator string) [][]model.MovieUrlInfo {
var res [][]model.MovieUrlInfo
if sparator != "" {
func ProcessPlayInfoV2(info, separator string) [][]system.MovieUrlInfo {
var res [][]system.MovieUrlInfo
if separator != "" {
// 1. 通过分隔符切分播放源地址
for _, l := range strings.Split(info, sparator) {
for _, l := range strings.Split(info, separator) {
// 只对m3u8播放源 和 .mp4下载地址进行处理
if strings.Contains(l, ".m3u8") || strings.Contains(l, ".mp4") {
// 2.对每个片源的集数和播放地址进行分割
var item []model.MovieUrlInfo
var item []system.MovieUrlInfo
for _, p := range strings.Split(l, "#") {
// 3. 处理 Episode$Link 形式的播放信息
if strings.Contains(p, "$") {
item = append(item, model.MovieUrlInfo{
item = append(item, system.MovieUrlInfo{
Episode: strings.Split(p, "$")[0],
Link: strings.Split(p, "$")[1],
})
} else {
item = append(item, model.MovieUrlInfo{
item = append(item, system.MovieUrlInfo{
Episode: "O(∩_∩)O",
Link: p,
})
@@ -132,16 +132,16 @@ func ProcessPlayInfoV2(info, sparator string) [][]model.MovieUrlInfo {
// 只对m3u8播放源 和 .mp4下载地址进行处理
if strings.Contains(info, ".m3u8") || strings.Contains(info, ".mp4") {
// 2.对每个片源的集数和播放地址进行分割
var item []model.MovieUrlInfo
var item []system.MovieUrlInfo
for _, p := range strings.Split(info, "#") {
// 3. 处理 Episode$Link 形式的播放信息
if strings.Contains(p, "$") {
item = append(item, model.MovieUrlInfo{
item = append(item, system.MovieUrlInfo{
Episode: strings.Split(p, "$")[0],
Link: strings.Split(p, "$")[1],
})
} else {
item = append(item, model.MovieUrlInfo{
item = append(item, system.MovieUrlInfo{
Episode: "O(∩_∩)O",
Link: p,
})

View File

@@ -2,8 +2,10 @@ package util
import (
"bufio"
"errors"
"os"
"path/filepath"
"server/config"
)
/*
@@ -11,11 +13,16 @@ import (
*/
// SaveOnlineFile 保存网络文件, 提供下载url和保存路径, 返回保存后的文件访问url相对路径
func SaveOnlineFile(url, dir string) (err error) {
func SaveOnlineFile(url, dir string) (path string, err error) {
// 请求获取文件内容
r := &RequestInfo{Uri: url}
ApiGet(r)
// 创建保存文件的目录
// 如果请求结果为空则直接跳过当前图片的同步, 等待后续触发时重试
if len(r.Resp) <= 0 {
err = errors.New("SyncPicture Failed: response is empty")
return
}
// 成功拿到图片数据 则创建保存文件的目录
if _, err = os.Stat(dir); os.IsNotExist(err) {
err = os.MkdirAll(dir, os.ModePerm)
if err != nil {
@@ -29,11 +36,18 @@ func SaveOnlineFile(url, dir string) (err error) {
return
}
defer file.Close()
//_, _ = file.Write(r.Resp)
// 将文件内容写入到file
writer := bufio.NewWriter(file)
_, err = writer.Write(r.Resp)
err = writer.Flush()
return
return filepath.Base(fileName), err
}
func CreateBaseDir() error {
// 如果不存在指定目录则创建该目录
if _, err := os.Stat(config.FilmPictureUploadDir); os.IsNotExist(err) {
return os.MkdirAll(config.FilmPictureUploadDir, os.ModePerm)
}
return nil
}

View File

@@ -36,7 +36,7 @@ func CreateClient() *colly.Collector {
c := colly.NewCollector()
// 设置请求使用clash的socks5代理
setProxy(c)
//setProxy(c)
// 设置代理信息
//if proxy, err := proxy.RoundRobinProxySwitcher("127.0.0.1:7890"); err != nil {
@@ -81,8 +81,8 @@ func ApiGet(r *RequestInfo) {
//extensions.Referer(Client)
// 请求成功后的响应
Client.OnResponse(func(response *colly.Response) {
// 将响应结构封装到 RequestInfo.Resp中
if len(response.Body) > 0 {
if (response.StatusCode == 200 || (response.StatusCode >= 300 && response.StatusCode <= 399)) && len(response.Body) > 0 {
// 将响应结构封装到 RequestInfo.Resp中
r.Resp = response.Body
} else {
r.Resp = []byte{}
@@ -99,6 +99,24 @@ func ApiGet(r *RequestInfo) {
}
}
// ApiTest 处理API请求后的数据, 主测试
func ApiTest(r *RequestInfo) error {
// 请求成功后的响应
Client.OnResponse(func(response *colly.Response) {
// 判断请求状态
if (response.StatusCode == 200 || (response.StatusCode >= 300 && response.StatusCode <= 399)) && len(response.Body) > 0 {
// 将响应结构封装到 RequestInfo.Resp中
r.Resp = response.Body
} else {
r.Resp = []byte{}
}
})
// 执行请求返回错误结果
err := Client.Visit(fmt.Sprintf("%s?%s", r.Uri, r.Params.Encode()))
log.Println(err)
return err
}
// 本地代理测试
func setProxy(c *colly.Collector) {
proxyUrl, _ := url.Parse("socks5://127.0.0.1:7890")

View File

@@ -0,0 +1,126 @@
package util
import (
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"log"
"net/url"
"regexp"
)
// GenerateUUID 生成UUID
func GenerateUUID() (uuid string) {
b := make([]byte, 16)
_, err := rand.Read(b)
if err != nil {
log.Fatal(err)
}
uuid = fmt.Sprintf("%X-%X-%X-%X-%X",
b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
return
}
// RandomString 生成指定长度两倍的随机字符串
func RandomString(length int) (uuid string) {
b := make([]byte, length)
_, err := rand.Read(b)
if err != nil {
log.Fatal(err)
}
uuid = fmt.Sprintf("%x", b)
return
}
// GenerateSalt 生成 length为16的随机字符串
func GenerateSalt() (uuid string) {
b := make([]byte, 8)
_, err := rand.Read(b)
if err != nil {
log.Fatal(err)
}
uuid = fmt.Sprintf("%X", b)
return
}
// PasswordEncrypt 密码加密 , (password+salt) md5 * 3
func PasswordEncrypt(password, salt string) string {
b := []byte(fmt.Sprint(password, salt)) // 将字符串转换为字节切片
var r [16]byte
for i := 0; i < 3; i++ {
r = md5.Sum(b) // 调用md5.Sum()函数进行加密
b = []byte(hex.EncodeToString(r[:]))
}
return hex.EncodeToString(r[:])
}
// ParsePriKeyBytes 解析私钥
func ParsePriKeyBytes(buf []byte) (*rsa.PrivateKey, error) {
p := &pem.Block{}
p, buf = pem.Decode(buf)
if p == nil {
return nil, errors.New("private key parse error")
}
return x509.ParsePKCS1PrivateKey(p.Bytes)
}
// ParsePubKeyBytes 解析公钥
func ParsePubKeyBytes(buf []byte) (*rsa.PublicKey, error) {
p, _ := pem.Decode(buf)
if p == nil {
return nil, errors.New("parse publicKey content nil")
}
pubKey, err := x509.ParsePKCS1PublicKey(p.Bytes)
if err != nil {
return nil, errors.New("x509.ParsePKCS1PublicKey error")
}
return pubKey, nil
}
// ValidDomain 域名校验(http://example.xxx)
func ValidDomain(s string) bool {
return regexp.MustCompile(`^(http|https)://[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*\.[a-z]{2,6}(:[0-9]{1,5})?$`).MatchString(s)
}
// ValidIPHost 校验是否符合http|https//ip 格式
func ValidIPHost(s string) bool {
return regexp.MustCompile(`^(http|https)://(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(:[0-9]{1,5})?$`).MatchString(s)
}
// ValidURL 校验http链接是否是符合规范的URL
func ValidURL(s string) bool {
_, err := url.ParseRequestURI(s)
if err != nil {
return false
}
return true
}
func ValidPwd(s string) error {
if len(s) < 8 || len(s) > 12 {
return fmt.Errorf("密码长度不符合规范, 必须为8-10位")
}
// 分别校验数字 大小写字母和特殊字符
num := `[0-9]{1}`
l := `[a-z]{1}`
u := `[A-Z]{1}`
symbol := `[!@#~$%^&*()+|_]{1}`
if b, err := regexp.MatchString(num, s); !b || err != nil {
return errors.New("密码必须包含数字 ")
}
if b, err := regexp.MatchString(l, s); !b || err != nil {
return errors.New("密码必须包含小写字母")
}
if b, err := regexp.MatchString(u, s); !b || err != nil {
return errors.New("密码必须包含大写字母")
}
if b, err := regexp.MatchString(symbol, s); !b || err != nil {
return errors.New("密码必须包含特殊字")
}
return nil
}