提交功能
This commit is contained in:
613
.gitattributes
vendored
Normal file
613
.gitattributes
vendored
Normal file
@@ -0,0 +1,613 @@
|
||||
# 视频,video
|
||||
# oggtheora
|
||||
*.[oO][gG][gG][tT][hH][eE][oO][rR][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# m2t
|
||||
*.[mM]2[tT] filter=lfs diff=lfs merge=binary -text
|
||||
# mts
|
||||
*.[mM][tT][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# mp4
|
||||
*.[mM][pP]4 filter=lfs diff=lfs merge=binary -text
|
||||
# avi
|
||||
*.[aA][vV][iI] filter=lfs diff=lfs merge=binary -text
|
||||
# mkv
|
||||
*.[mM][kK][vV] filter=lfs diff=lfs merge=binary -text
|
||||
# wmv
|
||||
*.[wW][mM][vV] filter=lfs diff=lfs merge=binary -text
|
||||
# asf
|
||||
*.[aA][sS][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# asx
|
||||
*.[aA][sS][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# rm
|
||||
*.[rR][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# rmvb
|
||||
*.[rR][mM][vV][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# 3gp
|
||||
*.3[gG][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# 3gpp
|
||||
*.3[gG][pP][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# 3gpp2
|
||||
*.3[gG][pP][pP]2 filter=lfs diff=lfs merge=binary -text
|
||||
# mov
|
||||
*.[mM][oO][vV] filter=lfs diff=lfs merge=binary -text
|
||||
# m4v
|
||||
*.[mM]4[vV] filter=lfs diff=lfs merge=binary -text
|
||||
# dat
|
||||
*.[dD][aA][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# vob
|
||||
*.[vV][oO][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# dv
|
||||
*.[dD][vV] filter=lfs diff=lfs merge=binary -text
|
||||
# mpeg
|
||||
*.[mM][pP][eE][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# mpg
|
||||
*.[mM][pP][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# mpe
|
||||
*.[mM][pP][eE] filter=lfs diff=lfs merge=binary -text
|
||||
# m2v
|
||||
*.[mM]2[vV] filter=lfs diff=lfs merge=binary -text
|
||||
# webm
|
||||
*.[wW][eE][bB][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# flv
|
||||
*.[fF][lL][vV] filter=lfs diff=lfs merge=binary -text
|
||||
# swf
|
||||
*.[sS][wW][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# avc
|
||||
*.[aA][vV][cC] filter=lfs diff=lfs merge=binary -text
|
||||
# arf
|
||||
*.[aA][rR][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# vcr
|
||||
*.[vV][cC][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# ogv
|
||||
*.[oO][gG][vV] filter=lfs diff=lfs merge=binary -text
|
||||
|
||||
# 音频, audio
|
||||
# ape
|
||||
*.[aA][pP][eE] filter=lfs diff=lfs merge=binary -text
|
||||
# wav
|
||||
*.[wW][aA][vV] filter=lfs diff=lfs merge=binary -text
|
||||
# m4a
|
||||
*.[mM]4[aA] filter=lfs diff=lfs merge=binary -text
|
||||
# mp3
|
||||
*.[mM][pP]3 filter=lfs diff=lfs merge=binary -text
|
||||
# flac
|
||||
*.[fF][lL][aA][cC] filter=lfs diff=lfs merge=binary -text
|
||||
# aif
|
||||
*.[aA][iI][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# aiff
|
||||
*.[aA][iI][fF][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# aac
|
||||
*.[aA][aA][cC] filter=lfs diff=lfs merge=binary -text
|
||||
# cpa
|
||||
*.[cC][pP][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# swa
|
||||
*.[sS][wW][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# sesx
|
||||
*.[sS][eE][sS][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# ses
|
||||
*.[sS][eE][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# bnk, Wwise audio
|
||||
*.[bB][nN][kK] filter=lfs diff=lfs merge=binary -text
|
||||
# wem, Wwise
|
||||
*.[wW][eE][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# pca
|
||||
*.[pP][cC][aA] filter=lfs diff=lfs merge=binary -text
|
||||
|
||||
# 库文件,Library
|
||||
# a
|
||||
*.[aA] filter=lfs diff=lfs merge=binary -text
|
||||
# o
|
||||
*.[oO] filter=lfs diff=lfs merge=binary -text
|
||||
# so
|
||||
*.[sS][oO] filter=lfs diff=lfs merge=binary -text
|
||||
# lib
|
||||
*.[lL][iI][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# dll
|
||||
*.[dD][lL][lL] filter=lfs diff=lfs merge=binary -text
|
||||
# lbr
|
||||
*.[lL][bB][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# tlb
|
||||
*.[tT][lL][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# cab
|
||||
*.[cC][aA][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# dylib
|
||||
*.[dD][yY][lL][iI][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# dsym
|
||||
*.[dD][sS][yY][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# app
|
||||
*.[aA][pP][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# ipa
|
||||
*.[iI][pP][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# dmg
|
||||
*.[dD][mM][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# exe
|
||||
*.[eE][xX][eE] filter=lfs diff=lfs merge=binary -text
|
||||
# pdb
|
||||
*.[pP][dD][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# dbg
|
||||
*.[dD][bB][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# run
|
||||
*.[rR][uU][nN] filter=lfs diff=lfs merge=binary -text
|
||||
# pyd
|
||||
*.[pP][yY][dD] filter=lfs diff=lfs merge=binary -text
|
||||
# pyc
|
||||
*.[pP][yY][cC] filter=lfs diff=lfs merge=binary -text
|
||||
# nupkg, NuGet package
|
||||
*.[nN][uU][pP][kK][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# pch
|
||||
*.[pP][cC][hH] filter=lfs diff=lfs merge=binary -text
|
||||
# ilk
|
||||
*.[iI][lL][kK] filter=lfs diff=lfs merge=binary -text
|
||||
# debug
|
||||
*.[dD][eE][bB][uU][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# obj
|
||||
*.[oO][bB][jJ] filter=lfs diff=lfs merge=binary -text
|
||||
# stub
|
||||
*.[sS][tT][uU][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# ddp
|
||||
*.[dD][dD][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# sym
|
||||
*.[sS][yY][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# lld
|
||||
*.[lL][lL][dD] filter=lfs diff=lfs merge=binary -text
|
||||
# res
|
||||
*.[rR][eE][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# locres
|
||||
*.[lL][oO][cC][rR][eE][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# aar
|
||||
*.[aA][aA][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# udd
|
||||
*.[uU][dD][dD] filter=lfs diff=lfs merge=binary -text
|
||||
# mdb
|
||||
*.[mM][dD][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# ddc
|
||||
*.[dD][dD][cC] filter=lfs diff=lfs merge=binary -text
|
||||
# udn
|
||||
*.[uU][dD][nN] filter=lfs diff=lfs merge=binary -text
|
||||
# h5
|
||||
*.[hH]5 filter=lfs diff=lfs merge=binary -text
|
||||
|
||||
|
||||
|
||||
# 压缩包,Archive format
|
||||
# =Archiving only=
|
||||
# ar
|
||||
*.[aA][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# cpio
|
||||
*.[cC][pP][iI][oO] filter=lfs diff=lfs merge=binary -text
|
||||
# shar
|
||||
*.[sS][hH][aA][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# tar
|
||||
*.[tT][aA][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# lbr
|
||||
*.[lL][bB][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# =Compression only=
|
||||
# Brotli
|
||||
*.[bB][rR][oO][tT][lL][iI] filter=lfs diff=lfs merge=binary -text
|
||||
# zip
|
||||
*.[zZ][iI][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# bzip2
|
||||
*.[bB][zZ][iI][pP]2 filter=lfs diff=lfs merge=binary -text
|
||||
# compress
|
||||
*.[cC][oO][mM][pP][rR][eE][sS][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# gzip
|
||||
*.[gG][zZ][iI][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# zopfli
|
||||
*.[zZ][oO][pP][fF][lL][iI] filter=lfs diff=lfs merge=binary -text
|
||||
# LZMA
|
||||
*.[lL][zZ][mM][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# LZ4
|
||||
*.[lL][zZ]4 filter=lfs diff=lfs merge=binary -text
|
||||
# lzip
|
||||
*.[lL][zZ][iI][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# lzop
|
||||
*.[lL][zZ][oO][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# SQ
|
||||
*.[sS][qQ] filter=lfs diff=lfs merge=binary -text
|
||||
# xz
|
||||
*.[xX][zZ] filter=lfs diff=lfs merge=binary -text
|
||||
# Zstandard
|
||||
*.[zZ][sS][tT][aA][nN][dD][aA][rR][dD] filter=lfs diff=lfs merge=binary -text
|
||||
# =Archiving and compression=
|
||||
# 7z
|
||||
*.7[zZ] filter=lfs diff=lfs merge=binary -text
|
||||
# ace
|
||||
*.[aA][cC][eE] filter=lfs diff=lfs merge=binary -text
|
||||
# arc
|
||||
*.[aA][rR][cC] filter=lfs diff=lfs merge=binary -text
|
||||
# arj
|
||||
*.[aA][rR][jJ] filter=lfs diff=lfs merge=binary -text
|
||||
# b1
|
||||
*.[bB]1 filter=lfs diff=lfs merge=binary -text
|
||||
# cabinet
|
||||
*.[cC][aA][bB][iI][nN][eE][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# cfs
|
||||
*.[cC][fF][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# cpt
|
||||
*.[cC][pP][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# dar
|
||||
*.[dD][aA][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# dgca
|
||||
*.[dD][gG][cC][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# dmg
|
||||
*.[dD][mM][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# egg
|
||||
*.[eE][gG][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# kgb
|
||||
*.[kK][gG][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# lha
|
||||
*.[lL][hH][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# lzx
|
||||
*.[lL][zZ][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# mpq
|
||||
*.[mM][pP][qQ] filter=lfs diff=lfs merge=binary -text
|
||||
# pea
|
||||
*.[pP][eE][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# rar
|
||||
*.[rR][aA][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# rzip
|
||||
*.[rR][zZ][iI][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# sit
|
||||
*.[sS][iI][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# sitx
|
||||
*.[sS][iI][tT][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# sqx
|
||||
*.[sS][qQ][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# uda
|
||||
*.[uU][dD][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# xar
|
||||
*.[xX][aA][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# zoo
|
||||
*.[zZ][oO][oO] filter=lfs diff=lfs merge=binary -text
|
||||
# zpaq
|
||||
*.[zZ][pP][aA][qQ] filter=lfs diff=lfs merge=binary -text
|
||||
# =Software packaging and distribution=
|
||||
# apk
|
||||
*.[aA][pP][kK] filter=lfs diff=lfs merge=binary -text
|
||||
# appx
|
||||
*.[aA][pP][pP][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# deb
|
||||
*.[dD][eE][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# rpm
|
||||
*.[rR][pP][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# msi
|
||||
*.[mM][sS][iI] filter=lfs diff=lfs merge=binary -text
|
||||
# ipa
|
||||
*.[iI][pP][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# jar
|
||||
*.[jJ][aA][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# war
|
||||
*.[wW][aA][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# ear
|
||||
*.[eE][aA][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# xap
|
||||
*.[xX][aA][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# xbap
|
||||
*.[xX][bB][aA][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# hap
|
||||
*.[hH][aA][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# app
|
||||
*.[aA][pP][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# gz
|
||||
*.[gG][zZ] filter=lfs diff=lfs merge=binary -text
|
||||
# tgz
|
||||
*.[tT][gG][zZ] filter=lfs diff=lfs merge=binary -text
|
||||
# bz2
|
||||
*.[bB][zZ]2 filter=lfs diff=lfs merge=binary -text
|
||||
# z
|
||||
*.[zZ] filter=lfs diff=lfs merge=binary -text
|
||||
# pak
|
||||
*.[pP][aA][kK] filter=lfs diff=lfs merge=binary -text
|
||||
# archive
|
||||
*.[aA][rR][cC][hH][iI][vV][eE] filter=lfs diff=lfs merge=binary -text
|
||||
# vsix
|
||||
*.[vV][sS][iI][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# disk image
|
||||
# iso
|
||||
*.[iI][sS][oO] filter=lfs diff=lfs merge=binary -text
|
||||
# bin
|
||||
*.[bB][iI][nN] filter=lfs diff=lfs merge=binary -text
|
||||
# cue
|
||||
*.[cC][uU][eE] filter=lfs diff=lfs merge=binary -text
|
||||
# raw
|
||||
*.[rR][aA][wW] filter=lfs diff=lfs merge=binary -text
|
||||
|
||||
# Adobe
|
||||
# Photoshop
|
||||
# psd
|
||||
*.[pP][sS][dD] filter=lfs diff=lfs merge=binary -text
|
||||
# Illustrator
|
||||
# ai
|
||||
*.[aA][iI] filter=lfs diff=lfs merge=binary -text
|
||||
# eps
|
||||
*.[eE][pP][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# pdf
|
||||
*.[pP][dD][fF] filter=lfs diff=lfs merge=binary -text
|
||||
|
||||
# 原始图片,Raw image
|
||||
# cr2
|
||||
*.[cC][rR]2 filter=lfs diff=lfs merge=binary -text
|
||||
# crw
|
||||
*.[cC][rR][wW] filter=lfs diff=lfs merge=binary -text
|
||||
# nef
|
||||
*.[nN][eE][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# nrw
|
||||
*.[nN][rR][wW] filter=lfs diff=lfs merge=binary -text
|
||||
# sr2
|
||||
*.[sS][rR]2 filter=lfs diff=lfs merge=binary -text
|
||||
# dng
|
||||
*.[dD][nN][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# arw
|
||||
*.[aA][rR][wW] filter=lfs diff=lfs merge=binary -text
|
||||
# ort
|
||||
*.[oO][rR][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# fbx
|
||||
*.[fF][bB][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# 3ds
|
||||
*.3[dD][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# xcf
|
||||
*.[xX][cC][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# hdr
|
||||
*.[hH][dD][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# duf
|
||||
*.[dD][uU][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# mb, maya
|
||||
*.[mM][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# cubemap,unity 贴图
|
||||
*.[cC][uU][bB][eE][mM][aA][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# navmesh,unity
|
||||
*.[nN][aA][vV][mM][eE][sS][hH] filter=lfs diff=lfs merge=binary -text
|
||||
# osm,地理数据
|
||||
*.[oO][sS][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# hip, houdini
|
||||
*.[hH][iI][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# cdr
|
||||
*.[cC][dD][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# raw
|
||||
*.[rR][aA][wW] filter=lfs diff=lfs merge=binary -text
|
||||
# dae
|
||||
*.[dD][aA][eE] filter=lfs diff=lfs merge=binary -text
|
||||
# hda, houdini
|
||||
*.[hH][dD][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# geo, houdini
|
||||
*.[gG][eE][oO] filter=lfs diff=lfs merge=binary -text
|
||||
# bgeo, houdini
|
||||
*.[bB][gG][eE][oO] filter=lfs diff=lfs merge=binary -text
|
||||
# ma, 3dmax
|
||||
*.[mM][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# max, 3dmax
|
||||
*.[mM][aA][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# 3dm, 3d模型
|
||||
*.3[dD][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# blend
|
||||
*.[bB][lL][eE][nN][dD] filter=lfs diff=lfs merge=binary -text
|
||||
# c4d
|
||||
*.[cC]4[dD] filter=lfs diff=lfs merge=binary -text
|
||||
# collada
|
||||
*.[cC][oO][lL][lL][aA][dD][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# dxf
|
||||
*.[dD][xX][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# jas
|
||||
*.[jJ][aA][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# lws
|
||||
*.[lL][wW][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# lxo
|
||||
*.[lL][xX][oO] filter=lfs diff=lfs merge=binary -text
|
||||
# ply
|
||||
*.[pP][lL][yY] filter=lfs diff=lfs merge=binary -text
|
||||
# skp
|
||||
*.[sS][kK][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# stl
|
||||
*.[sS][tT][lL] filter=lfs diff=lfs merge=binary -text
|
||||
# ztl
|
||||
*.[zZ][tT][lL] filter=lfs diff=lfs merge=binary -text
|
||||
# it
|
||||
*.[iI][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# mod
|
||||
*.[mM][oO][dD] filter=lfs diff=lfs merge=binary -text
|
||||
# ogg
|
||||
*.[oO][gG][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# s3m
|
||||
*.[sS]3[mM] filter=lfs diff=lfs merge=binary -text
|
||||
# xm
|
||||
*.[xX][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# glb
|
||||
*.[gG][lL][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# gltf
|
||||
*.[gG][lL][tT][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# off
|
||||
*.[oO][fF][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# wrl
|
||||
*.[wW][rR][lL] filter=lfs diff=lfs merge=binary -text
|
||||
# 3mf
|
||||
*.3[mM][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# amf
|
||||
*.[aA][mM][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# ifc
|
||||
*.[iI][fF][cC] filter=lfs diff=lfs merge=binary -text
|
||||
# brep
|
||||
*.[bB][rR][eE][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# step
|
||||
*.[sS][tT][eE][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# fcstd
|
||||
*.[fF][cC][sS][tT][dD] filter=lfs diff=lfs merge=binary -text
|
||||
# bim
|
||||
*.[bB][iI][mM] filter=lfs diff=lfs merge=binary -text
|
||||
|
||||
# 图像,Image
|
||||
# jpg
|
||||
*.[jJ][pP][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# jpeg
|
||||
*.[jJ][pP][eE][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# tiff
|
||||
*.[tT][iI][fF][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# gif
|
||||
*.[gG][iI][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# svg
|
||||
*.[sS][vV][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# svgz
|
||||
*.[sS][vV][gG][zZ] filter=lfs diff=lfs merge=binary -text
|
||||
# bmp
|
||||
*.[bB][mM][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# png
|
||||
*.[pP][nN][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# tif
|
||||
*.[tT][iI][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# tga
|
||||
*.[tT][gG][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# prj
|
||||
*.[pP][rR][jJ] filter=lfs diff=lfs merge=binary -text
|
||||
# dwg
|
||||
*.[dD][wW][gG] filter=lfs diff=lfs merge=binary -text
|
||||
# flt
|
||||
*.[fF][lL][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# htr
|
||||
*.[hH][tT][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# iges
|
||||
*.[iI][gG][eE][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# igs
|
||||
*.[iI][gG][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# ige
|
||||
*.[iI][gG][eE] filter=lfs diff=lfs merge=binary -text
|
||||
# ipt
|
||||
*.[iI][pP][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# iam
|
||||
*.[iI][aA][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# lp
|
||||
*.[lL][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# ls
|
||||
*.[lL][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# shp
|
||||
*.[sS][hH][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# aep
|
||||
*.[aA][eE][pP] filter=lfs diff=lfs merge=binary -text
|
||||
# psb
|
||||
*.[pP][sS][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# edx
|
||||
*.[eE][dD][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# cds
|
||||
*.[cC][dD][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# exr
|
||||
*.[eE][xX][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# bc
|
||||
*.[bB][cC] filter=lfs diff=lfs merge=binary -text
|
||||
|
||||
|
||||
# 文档,Document
|
||||
# Microsoft Excel
|
||||
# xls
|
||||
*.[xX][lL][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# xlsx
|
||||
*.[xX][lL][sS][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# xslsm
|
||||
*.[xX][sS][lL][sS][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# xlt
|
||||
*.[xX][lL][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# xltx
|
||||
*.[xX][lL][tT][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# xltm
|
||||
*.[xX][lL][tT][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# Microsoft powperpoint
|
||||
# ppt
|
||||
*.[pP][pP][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# pptx
|
||||
*.[pP][pP][tT][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# pps
|
||||
*.[pP][pP][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# ppsx
|
||||
*.[pP][pP][sS][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# ppsm
|
||||
*.[pP][pP][sS][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# pptm
|
||||
*.[pP][pP][tT][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# pot
|
||||
*.[pP][oO][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# potm
|
||||
*.[pP][oO][tT][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# Microsoft word
|
||||
# doc
|
||||
*.[dD][oO][cC] filter=lfs diff=lfs merge=binary -text
|
||||
# docx
|
||||
*.[dD][oO][cC][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# docm
|
||||
*.[dD][oO][cC][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# dot
|
||||
*.[dD][oO][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# dotx
|
||||
*.[dD][oO][tT][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# dotm
|
||||
*.[dD][oO][tT][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# Apple keynotes
|
||||
# key
|
||||
*.[kK][eE][yY] filter=lfs diff=lfs merge=binary -text
|
||||
# Apple pages
|
||||
# pages, apple
|
||||
*.[pP][aA][gG][eE][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# Apple numbers
|
||||
# numbers, apple
|
||||
*.[nN][uU][mM][bB][eE][rR][sS] filter=lfs diff=lfs merge=binary -text
|
||||
|
||||
# 电子书,Book
|
||||
# chm
|
||||
*.[cC][hH][mM] filter=lfs diff=lfs merge=binary -text
|
||||
# mobi
|
||||
*.[mM][oO][bB][iI] filter=lfs diff=lfs merge=binary -text
|
||||
# epub
|
||||
*.[eE][pP][uU][bB] filter=lfs diff=lfs merge=binary -text
|
||||
# azw
|
||||
*.[aA][zZ][wW] filter=lfs diff=lfs merge=binary -text
|
||||
# azw3
|
||||
*.[aA][zZ][wW]3 filter=lfs diff=lfs merge=binary -text
|
||||
# iba
|
||||
*.[iI][bB][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# lrs
|
||||
*.[lL][rR][sS] filter=lfs diff=lfs merge=binary -text
|
||||
# lrf
|
||||
*.[lL][rR][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# lrx
|
||||
*.[lL][rR][xX] filter=lfs diff=lfs merge=binary -text
|
||||
# djvu
|
||||
*.[dD][jJ][vV][uU] filter=lfs diff=lfs merge=binary -text
|
||||
# lit
|
||||
*.[lL][iI][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# rft
|
||||
*.[rR][fF][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# cbr
|
||||
*.[cC][bB][rR] filter=lfs diff=lfs merge=binary -text
|
||||
# cbz
|
||||
*.[cC][bB][zZ] filter=lfs diff=lfs merge=binary -text
|
||||
# cb7
|
||||
*.[cC][bB]7 filter=lfs diff=lfs merge=binary -text
|
||||
# cbt
|
||||
*.[cC][bB][tT] filter=lfs diff=lfs merge=binary -text
|
||||
# cba
|
||||
*.[cC][bB][aA] filter=lfs diff=lfs merge=binary -text
|
||||
# pdb
|
||||
*.[pP][dD][bB] filter=lfs diff=lfs merge=binary -text
|
||||
|
||||
# 字体,font
|
||||
# ttf
|
||||
*.[tT][tT][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# otf
|
||||
*.[oO][tT][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# woff
|
||||
*.[wW][oO][fF][fF] filter=lfs diff=lfs merge=binary -text
|
||||
# woff2
|
||||
*.[wW][oO][fF][fF]2 filter=lfs diff=lfs merge=binary -text
|
||||
|
||||
# 翻译,translate
|
||||
# po
|
||||
*.[pP][oO] filter=lfs diff=lfs merge=binary -text
|
||||
# auto generated by UGit
|
||||
*.bundle filter=lfs diff=lfs merge=binary -text
|
||||
*.dll filter=lfs diff=lfs merge=binary -text
|
||||
*.exe filter=lfs diff=lfs merge=binary -text
|
||||
*.zip filter=lfs diff=lfs merge=binary -text
|
||||
*.mp4 filter=lfs diff=lfs merge=binary -text
|
||||
*.so filter=lfs diff=lfs merge=binary -text
|
||||
*.dylib filter=lfs diff=lfs merge=binary -text
|
||||
*.a filter=lfs diff=lfs merge=binary -text
|
||||
*.pdb filter=lfs diff=lfs merge=binary -text
|
||||
*.cache filter=lfs diff=lfs merge=binary -text
|
||||
*.png filter=lfs diff=lfs merge=binary -text
|
||||
*.db filter=lfs diff=lfs merge=binary -text
|
||||
|
||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
bin/
|
||||
obj/
|
||||
/packages/
|
||||
riderModule.iml
|
||||
/_ReSharper.Caches/
|
||||
211
.idea/.idea.ACBuildService/.idea/workspace.xml
generated
Normal file
211
.idea/.idea.ACBuildService/.idea/workspace.xml
generated
Normal file
@@ -0,0 +1,211 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoGeneratedRunConfigurationManager">
|
||||
<projectFile>ACBuildService.csproj</projectFile>
|
||||
</component>
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="1ed80655-443d-428d-8747-9708bc7b56ea" name="更改" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/Db/DB.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Db/Tables/DeviceTable.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Db/Tables/VideoTable.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Http/Extensions/DateTimeExtensions.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Http/Extensions/FileNameExtensions.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Http/Page/ApiController.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Http/Page/Args.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Http/Page/HomeController.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Http/Page/NBControllerBase.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Http/SignValidationAttribute.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/VideoDownload/DouyinShareRouterData.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/VideoDownload/Platforms/DouYin.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/VideoDownload/Platforms/DownloadPlatforms.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/VideoDownload/Platforms/KuaiShou.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/VideoDownload/VideoDownload.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/VideoDownload/VideoDownloadService.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/VideoDownload/VideoModel.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.ACBuildService/.idea/.gitignore" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.ACBuildService/.idea/.name" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.ACBuildService/.idea/encodings.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.ACBuildService/.idea/indexLayout.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.ACBuildService/.idea/jsLibraryMappings.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.ACBuildService/.idea/riderPublish.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.ACBuildService/.idea/vcs.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ACBuildService.csproj" beforeDir="false" afterPath="$PROJECT_DIR$/BabyVideoService.csproj" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ACBuildService.sln" beforeDir="false" afterPath="$PROJECT_DIR$/BabyVideoService.sln" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ACBuildService.sln.DotSettings.user" beforeDir="false" afterPath="$PROJECT_DIR$/ACBuildService.sln.DotSettings.user" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/App.cs" beforeDir="false" afterPath="$PROJECT_DIR$/App.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/AppSettingsConfigs.cs" beforeDir="false" afterPath="$PROJECT_DIR$/AppSettingsConfigs.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/GoogleCloud/GoogleCloud.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/GoogleCloud/UploadFileTask.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/GoogleCloud/UploadGoogleCloudTask.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Http/ErrorCode.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Http/ErrorCode.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Http/Extensions/HttpContextExtension.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Http/Extensions/HttpContextExtension.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Http/HttpHandler.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Http/HttpPage.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Http/HttpService.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Http/HttpService.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Http/HttpSmbHandler.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Utils/FileUtil.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Utils/FileUtil.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/appsettings.json" beforeDir="false" afterPath="$PROJECT_DIR$/appsettings.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/wwwroot/cdn.html" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/wwwroot/clipboard.html" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/wwwroot/file_list.html" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/wwwroot/home.html" beforeDir="false" afterPath="$PROJECT_DIR$/wwwroot/home.html" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/wwwroot/log.html" beforeDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="DpaMonitoringSettings">
|
||||
<option name="firstShow" value="false" />
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="HTML File" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="HighlightingSettingsPerFile">
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/56fad711d44d4d47bc9f3128de5ae30ac90920/14/78d2f3c4/CultureInfo.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/759e68a39ef64bf8b91a2ed761bcd8a92e3400/05/7b368181/ISugarQueryable`1.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/759e68a39ef64bf8b91a2ed761bcd8a92e3400/59/e6a3fb28/IInsertable`1.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/83d0691b2ff94d50bae98091380d202e27e00/40/dca6e351/StorageClient.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/9a4eaacbc57349edb521efd6830794901f4910/b4/311bb478/MD5.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/ba9546ad90c246358f902e6522c620ddc9910/71/404fbeda/EndpointRouteBuilderExtensions.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/bbcd33dffc534f7b961b0763775ac78b1de938/f9/08f50080/ControllerBase.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/fb4ef246b9c147be90cf03bb4a45b1ce20938/a1/2cc30e09/Channel`2.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/59cd7a17e4fcffda1ba3687b386939b4e155ba482f85c8fe9993bc8373d7f93/ApiBehaviorApplicationModelProvider.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/9492f6e132137ff2698b3268c9c422a578e49c5893a8371ed19fb0695fd5925/AbstractDownloadService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Db/DB.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Db/Tables/DeviceTable.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Db/Tables/VideoTable.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Http/Extensions/DateTimeExtensions.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Http/Extensions/FileNameExtensions.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Http/HttpService.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Http/Page/ApiController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Http/Page/Args.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Http/Page/HomeController.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Http/Page/NBControllerBase.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/Http/SignValidationAttribute.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/VideoDownload/DouyinShareRouterData.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/VideoDownload/Platforms/DouYin.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/VideoDownload/Platforms/DownloadPlatforms.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/VideoDownload/Platforms/KuaiShou.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/VideoDownload/VideoDownload.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
<setting file="file://$PROJECT_DIR$/VideoDownload/VideoModel.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo">{
|
||||
"associatedIndex": 8
|
||||
}</component>
|
||||
<component name="ProjectId" id="38V6rHTZQlHzbOTn9ymyVhZ9eqD" />
|
||||
<component name="ProjectLevelVcsManager">
|
||||
<ConfirmationsSetting value="2" id="Add" />
|
||||
</component>
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">{
|
||||
"keyToString": {
|
||||
".NET 项目.ACBuildService.executor": "Debug",
|
||||
".NET 项目.BabyVideoService.executor": "Debug",
|
||||
"DefaultHtmlFileTemplate": "HTML File",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.git.unshallow": "true",
|
||||
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
||||
"git-widget-placeholder": "master",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"settings.editor.selected.configurable": "configurable.group.editor",
|
||||
"vue.rearranger.settings.migration": "true",
|
||||
"发布到文件夹.Publish ACBuildService to folder.executor": "Run"
|
||||
}
|
||||
}</component>
|
||||
<component name="RunManager" selected=".NET 项目.BabyVideoService">
|
||||
<configuration name="Publish ACBuildService to folder" type="DotNetFolderPublish" factoryName="Publish to folder">
|
||||
<riderPublish configuration="Release" delete_existing_files="true" platform="Any CPU" produce_single_file="true" self_contained="true" target_folder="$PROJECT_DIR$/bin/Release/net8.0/win-x64/publish" target_framework="net8.0" uuid_high="-3297046778019885416" uuid_low="-4999719437998725852">
|
||||
<runtimes>
|
||||
<item value="win-x64" />
|
||||
</runtimes>
|
||||
</riderPublish>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="BabyVideoService" type="DotNetProject" factoryName=".NET Project">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/bin/Debug/net8.0/BabyVideoService.exe" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/bin/Debug/net8.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="ENV_FILE_PATHS" value="" />
|
||||
<option name="REDIRECT_INPUT_PATH" value="" />
|
||||
<option name="MIXED_MODE_DEBUG" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="AUTO_ATTACH_CHILDREN" value="0" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/BabyVideoService.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="net8.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
</configuration>
|
||||
<list>
|
||||
<item itemvalue=".NET 项目.BabyVideoService" />
|
||||
<item itemvalue="发布到文件夹.Publish ACBuildService to folder" />
|
||||
</list>
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="默认任务">
|
||||
<changelist id="1ed80655-443d-428d-8747-9708bc7b56ea" name="更改" comment="" />
|
||||
<created>1768872588133</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1768872588133</updated>
|
||||
<workItem from="1768872589085" duration="31265000" />
|
||||
<workItem from="1769505886159" duration="1492000" />
|
||||
<workItem from="1770512793250" duration="25168000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="UnityProjectConfiguration" hasMinimizedUI="false" />
|
||||
<component name="VcsManagerConfiguration">
|
||||
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager>
|
||||
<breakpoints>
|
||||
<breakpoint enabled="true" type="DotNet_Exception_Breakpoints">
|
||||
<properties exception="System.OperationCanceledException" breakIfHandledByOtherCode="false" displayValue="System.OperationCanceledException" />
|
||||
<option name="timeStamp" value="1" />
|
||||
</breakpoint>
|
||||
<breakpoint enabled="true" type="DotNet_Exception_Breakpoints">
|
||||
<properties exception="System.Threading.Tasks.TaskCanceledException" breakIfHandledByOtherCode="false" displayValue="System.Threading.Tasks.TaskCanceledException" />
|
||||
<option name="timeStamp" value="2" />
|
||||
</breakpoint>
|
||||
<breakpoint enabled="true" type="DotNet_Exception_Breakpoints">
|
||||
<properties exception="System.Threading.ThreadAbortException" breakIfHandledByOtherCode="false" displayValue="System.Threading.ThreadAbortException" />
|
||||
<option name="timeStamp" value="3" />
|
||||
</breakpoint>
|
||||
</breakpoints>
|
||||
</breakpoint-manager>
|
||||
</component>
|
||||
<component name="XSLT-Support.FileAssociations.UIState">
|
||||
<expand />
|
||||
<select />
|
||||
</component>
|
||||
</project>
|
||||
13
.idea/.idea.BabyVideoService/.idea/.gitignore
generated
vendored
Normal file
13
.idea/.idea.BabyVideoService/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# 默认忽略的文件
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider 忽略的文件
|
||||
/.idea.S3Update.iml
|
||||
/contentModel.xml
|
||||
/projectSettingsUpdater.xml
|
||||
/modules.xml
|
||||
# 基于编辑器的 HTTP 客户端请求
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
4
.idea/.idea.BabyVideoService/.idea/encodings.xml
generated
Normal file
4
.idea/.idea.BabyVideoService/.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||
</project>
|
||||
8
.idea/.idea.BabyVideoService/.idea/indexLayout.xml
generated
Normal file
8
.idea/.idea.BabyVideoService/.idea/indexLayout.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/.idea.BabyVideoService/.idea/jsLibraryMappings.xml
generated
Normal file
6
.idea/.idea.BabyVideoService/.idea/jsLibraryMappings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptLibraryMappings">
|
||||
<file url="PROJECT" libraries="{jquery}" />
|
||||
</component>
|
||||
</project>
|
||||
10
.idea/.idea.BabyVideoService/.idea/riderPublish.xml
generated
Normal file
10
.idea/.idea.BabyVideoService/.idea/riderPublish.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="LocationsWithSilentDeleteHolder">
|
||||
<option name="locations">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/bin/Release/net7.0/win-x64/publish" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/.idea.BabyVideoService/.idea/vcs.xml
generated
Normal file
6
.idea/.idea.BabyVideoService/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
151
.idea/.idea.S3Update/.idea/workspace.xml
generated
Normal file
151
.idea/.idea.S3Update/.idea/workspace.xml
generated
Normal file
@@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoGeneratedRunConfigurationManager">
|
||||
<projectFile>S3Update.csproj</projectFile>
|
||||
</component>
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="a22442a9-c22e-4925-9d61-0e7b123dd791" name="更改" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/ACBuildService.sln" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/AmazonS3/AmazonS3Uploader.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/App.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/AppSettingsConfigs.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/DAO/BuildInfo.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/DingTalk/DingTalkService.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/DingTalk/DingTalkTestData.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Http/HttpHandler.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Http/HttpService.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Http/Test.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Program.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/S3Update.csproj" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Template/AppNotice.md" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Utils.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/appsettings.json" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="JSON File" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="HighlightingSettingsPerFile">
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/125a503bdb47420aa159999f50c6f427b16a0/63/cd0e14c5/AmazonS3Client.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/125a503bdb47420aa159999f50c6f427b16a0/a5/d29319ae/IAmazonS3.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/272f80b23bc042ef81ba3ab7ea4ecddb16b880/94/999b8d74/JsonSerializer.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/4153965b14f14480b9485bd6302acddec8a0/48/c9be6245/JsonConfigurationExtensions.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/53e60aab468843af866c5896ad5ea72d2178a0/42/0bd35d8f/KestrelServerLimits.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/53e60aab468843af866c5896ad5ea72d2178a0/51/b874eb72/KestrelServerOptions.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/5f8fb2e16be44b11b2ee143f4b77491e408a0/f3/2d0d331a/FormOptions.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/6eb64a83264b490faecaf5d9f80c71fd1e38b0/a7/e37813ca/StatusCodeResult.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/aa813094324f408e8047b0dda3853621b1d878/8c/9ddbd145/FileStream.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/c7c18550c3384b22ad98cb17afcdcb8ff880/c3/fe8586e4/HttpUtility.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/d029ce1eb56a43518a6f641c75e05c69c08a0/8d/04decdcd/EndpointRouteBuilderExtensions.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/d0903c2b0b994c838944152abd1164d04b8a0/27/cee45528/HttpRequest.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/df62c8d50e2f42c8be5b0988aa88459d118b0/0e/2ef98457/IFormCollection.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/df62c8d50e2f42c8be5b0988aa88459d118b0/54/bba95950/IFormFileCollection.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/e59a47c0febb43d581d8863e7367eb611ab878/d5/6c014dc6/HttpClient.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/fe558445f2644cc7bce69050fb3e956c1b7ca0/4c/6616a00b/ClientConfig.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/fe558445f2644cc7bce69050fb3e956c1b7ca0/a3/f9fafb87/RegionEndpoint.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/3bd14eb0aff9eef09c97aab46a4e2efb4447d1d32344eb947ffac2f9ab8/WebHostBuilderExtensions.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/4dc731a2825b3b282c3a7fc5adbea47e8720eadf5445558010f8488ec05eb64f/HttpClient.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/bd1d5c50194fea68ff3559c160230b0ab50f5acf4ce3061bffd6d62958e2182/ExceptionDispatchInfo.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/c7a4689271bd1d191f6aaf905f158992a7d36de3f142326e6f6c892997a2dd3/ByteArrayContent.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/d97a692897faa346d6c839abe34fef633777e8a5199569218619a7e48769c65f/StreamReader.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/e60b8a28a674789a73bf80f2349c8fd7881cb1ed21fea431b814f1e08598/Convert.cs" root0="SKIP_HIGHLIGHTING" />
|
||||
</component>
|
||||
<component name="MarkdownSettingsMigration">
|
||||
<option name="stateVersion" value="1" />
|
||||
</component>
|
||||
<component name="ProjectId" id="2R5esRCxK3XGnIL0YuG3qDdD3DH" />
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
|
||||
<ConfirmationsSetting value="2" id="Add" />
|
||||
</component>
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">{
|
||||
"keyToString": {
|
||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"WebServerToolWindowFactoryState": "false",
|
||||
"git-widget-placeholder": "master",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
},
|
||||
"keyToStringList": {
|
||||
"rider.external.source.directories": [
|
||||
"C:\\Users\\Bob\\AppData\\Roaming\\JetBrains\\Rider2023.1\\resharper-host\\DecompilerCache",
|
||||
"C:\\Users\\Bob\\AppData\\Roaming\\JetBrains\\Rider2023.1\\resharper-host\\SourcesCache",
|
||||
"C:\\Users\\Bob\\AppData\\Local\\Symbols\\src"
|
||||
]
|
||||
}
|
||||
}</component>
|
||||
<component name="RunManager" selected="发布到文件夹.Win">
|
||||
<configuration name="Win" type="DotNetFolderPublish" factoryName="Publish to folder">
|
||||
<riderPublish configuration="Release" delete_existing_files="true" platform="Any CPU" produce_single_file="true" runtime="win-x64" target_folder="$PROJECT_DIR$/bin/Release/net7.0/win-x64/publish" target_framework="net7.0" uuid_high="-3297046778019885416" uuid_low="-4999719437998725852" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="S3Update" type="DotNetProject" factoryName=".NET Project">
|
||||
<option name="EXE_PATH" value="$PROJECT_DIR$/bin/Debug/net7.0/S3Update.exe" />
|
||||
<option name="PROGRAM_PARAMETERS" value="http src=1 test=2" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/bin/Debug/net7.0" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/S3Update.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value="net7.0" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
</configuration>
|
||||
<list>
|
||||
<item itemvalue=".NET 项目.S3Update" />
|
||||
<item itemvalue="发布到文件夹.Win" />
|
||||
</list>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="应用程序级" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="默认任务">
|
||||
<changelist id="a22442a9-c22e-4925-9d61-0e7b123dd791" name="更改" comment="" />
|
||||
<created>1686544575807</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1686544575807</updated>
|
||||
<workItem from="1686544577339" duration="14232000" />
|
||||
<workItem from="1686624244302" duration="14867000" />
|
||||
<workItem from="1686708589206" duration="4021000" />
|
||||
<workItem from="1686879973338" duration="137000" />
|
||||
<workItem from="1686880397386" duration="11663000" />
|
||||
<workItem from="1687137892768" duration="7503000" />
|
||||
<workItem from="1687742766796" duration="2228000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
BIN
.vs/ACBuildService/v17/.suo
Normal file
BIN
.vs/ACBuildService/v17/.suo
Normal file
Binary file not shown.
BIN
.vs/ProjectEvaluation/acbuildservice.metadata.v6.1
Normal file
BIN
.vs/ProjectEvaluation/acbuildservice.metadata.v6.1
Normal file
Binary file not shown.
BIN
.vs/ProjectEvaluation/acbuildservice.projects.v6.1
Normal file
BIN
.vs/ProjectEvaluation/acbuildservice.projects.v6.1
Normal file
Binary file not shown.
10
ACBuildService.sln.DotSettings.user
Normal file
10
ACBuildService.sln.DotSettings.user
Normal file
@@ -0,0 +1,10 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACultureInfo_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F56fad711d44d4d47bc9f3128de5ae30ac90920_003F14_003F78d2f3c4_003FCultureInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFile_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5147b10c5a8c4522b56fba0a889139cfc8f908_003F1b_003F1029da80_003FFile_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFormOptions_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbe70df8bcbbf4fdbb727e7194c8cd235e510_003F8a_003Fab2ee68d_003FFormOptions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpUtility_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbb2917bd97f04a3bbe43bb4d35dae565e908_003Fda_003F1ba0545f_003FHttpUtility_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALogLevel_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3928f30d38a74d899dcf80c80e3944ccddc00_003F98_003F04c78b53_003FLogLevel_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARoutePatternParser_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F3831116b66390bb3a7f83dd22df6aab756e1807336836727888e69a5b413a_003FRoutePatternParser_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AStorageClient_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F83d0691b2ff94d50bae98091380d202e27e00_003F8c_003Ff8d922d0_003FStorageClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AStorageClient_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F83d0691b2ff94d50bae98091380d202e27e00_003F40_003Fdca6e351_003FStorageClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AString_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5147b10c5a8c4522b56fba0a889139cfc8f908_003Fd9_003F39b4342b_003FString_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
||||
51
App.cs
Normal file
51
App.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using SqlSugar;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
public static class App
|
||||
{
|
||||
public static bool Running { get; set; }
|
||||
public static AppSettingsConfigs Settings = new AppSettingsConfigs();
|
||||
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
Running = true;
|
||||
LoadSetting();
|
||||
DB.InitDb();
|
||||
}
|
||||
|
||||
public static void LoadSetting()
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||
.Build();
|
||||
|
||||
var config = configuration.Get<AppSettingsConfigs>(); //绑定到实体
|
||||
if (config != null)
|
||||
{
|
||||
Settings = config;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IOException("配置文件读取失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region Update
|
||||
|
||||
internal static void Update()
|
||||
{
|
||||
Time.Update();
|
||||
}
|
||||
|
||||
internal static void LateUpdate()
|
||||
{
|
||||
Time.LateUpdate();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
29
AppSettingsConfigs.cs
Normal file
29
AppSettingsConfigs.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
namespace ACBuildService;
|
||||
|
||||
public class AppSettingsConfigs
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否开启Debug模式
|
||||
/// </summary>
|
||||
public bool Debug { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// http服务地址
|
||||
/// </summary>
|
||||
public int HttpPort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否开启代理
|
||||
/// </summary>
|
||||
public bool OpenProxy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 代理地址
|
||||
/// </summary>
|
||||
public string ProxyHost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
}
|
||||
47
BabyVideoService.csproj
Normal file
47
BabyVideoService.csproj
Normal file
@@ -0,0 +1,47 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable>
|
||||
<RootNamespace>S3Update</RootNamespace>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<None Update="Temp\AppNotice.md">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="project-game-x-f720ef30f678.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="wwwroot\assets\bootstrap.min.css">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="wwwroot\assets\bootstrap.min.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="wwwroot\assets\jquery.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="wwwroot\home.html">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Downloader" Version="4.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
|
||||
<PackageReference Include="NLog" Version="5.2.0" />
|
||||
<PackageReference Include="NLog.Web" Version="5.3.0" />
|
||||
<PackageReference Include="RestSharp" Version="113.1.0" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.211" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
16
BabyVideoService.sln
Normal file
16
BabyVideoService.sln
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BabyVideoService", "BabyVideoService.csproj", "{D23E896C-8447-4E98-BA9D-6DA929786524}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D23E896C-8447-4E98-BA9D-6DA929786524}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D23E896C-8447-4E98-BA9D-6DA929786524}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D23E896C-8447-4E98-BA9D-6DA929786524}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D23E896C-8447-4E98-BA9D-6DA929786524}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
16
BabyVideoService.sln.DotSettings.user
Normal file
16
BabyVideoService.sln.DotSettings.user
Normal file
@@ -0,0 +1,16 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAbstractDownloadService_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F9492f6e132137ff2698b3268c9c422a578e49c5893a8371ed19fb0695fd5925_003FAbstractDownloadService_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AApiBehaviorApplicationModelProvider_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F59cd7a17e4fcffda1ba3687b386939b4e155ba482f85c8fe9993bc8373d7f93_003FApiBehaviorApplicationModelProvider_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AChannel_00602_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ffb4ef246b9c147be90cf03bb4a45b1ce20938_003Fa1_003F2cc30e09_003FChannel_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AControllerBase_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbbcd33dffc534f7b961b0763775ac78b1de938_003Ff9_003F08f50080_003FControllerBase_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACultureInfo_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F56fad711d44d4d47bc9f3128de5ae30ac90920_003F14_003F78d2f3c4_003FCultureInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEndpointRouteBuilderExtensions_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fba9546ad90c246358f902e6522c620ddc9910_003F71_003F404fbeda_003FEndpointRouteBuilderExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFile_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5147b10c5a8c4522b56fba0a889139cfc8f908_003F1b_003F1029da80_003FFile_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFormOptions_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbe70df8bcbbf4fdbb727e7194c8cd235e510_003F8a_003Fab2ee68d_003FFormOptions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpUtility_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbb2917bd97f04a3bbe43bb4d35dae565e908_003Fda_003F1ba0545f_003FHttpUtility_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AISugarQueryable_00601_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F759e68a39ef64bf8b91a2ed761bcd8a92e3400_003F05_003F7b368181_003FISugarQueryable_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALogLevel_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3928f30d38a74d899dcf80c80e3944ccddc00_003F98_003F04c78b53_003FLogLevel_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARoutePatternParser_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003F3831116b66390bb3a7f83dd22df6aab756e1807336836727888e69a5b413a_003FRoutePatternParser_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AStorageClient_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F83d0691b2ff94d50bae98091380d202e27e00_003F8c_003Ff8d922d0_003FStorageClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AStorageClient_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F83d0691b2ff94d50bae98091380d202e27e00_003F40_003Fdca6e351_003FStorageClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AString_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5147b10c5a8c4522b56fba0a889139cfc8f908_003Fd9_003F39b4342b_003FString_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
||||
106
Core/Task/Collection/ParallelTaskCollection.cs
Normal file
106
Core/Task/Collection/ParallelTaskCollection.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
namespace NBC
|
||||
{
|
||||
public class ParallelTaskCollection : TaskCollection
|
||||
{
|
||||
private int _currentIndex;
|
||||
|
||||
/// <summary>
|
||||
/// 最大并行数量 (默认为9)
|
||||
/// </summary>
|
||||
public int ParallelNum = 9;
|
||||
|
||||
protected override NTaskStatus RunTasksAndCheckIfDone()
|
||||
{
|
||||
var st = NTaskStatus.Running;
|
||||
|
||||
if (CurRunTask.Count < ParallelNum && _currentIndex < RawList.Count)
|
||||
{
|
||||
var num = ParallelNum - CurRunTask.Count;
|
||||
for (var index = 0; index < num; index++)
|
||||
if (_currentIndex < RawList.Count)
|
||||
{
|
||||
CurRunTask.Add(RawList[_currentIndex]);
|
||||
_currentIndex += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (var index = 0; index < CurrentTask.Count; index++)
|
||||
{
|
||||
var element = CurrentTask[index];
|
||||
var childSt = element.Process();
|
||||
|
||||
if (FailBreak && childSt == NTaskStatus.Fail)
|
||||
{
|
||||
_errorMsg = element.ErrorMsg;
|
||||
st = NTaskStatus.Fail;
|
||||
break;
|
||||
}
|
||||
|
||||
if (childSt == NTaskStatus.Success || childSt == NTaskStatus.Fail)
|
||||
{
|
||||
CurrentTask.RemoveAt(index);
|
||||
index--;
|
||||
FinishList.Add(element);
|
||||
}
|
||||
}
|
||||
|
||||
if (FinishList.Count >= RawList.Count) st = NTaskStatus.Success;
|
||||
|
||||
// for (var index = 0; index < CurrentTask.Count; index++)
|
||||
// {
|
||||
// var element = CurrentTask[index];
|
||||
// var childSt = element.Process();
|
||||
//
|
||||
// if (childSt >= Status.Success)
|
||||
// {
|
||||
// if (FailBreak && childSt == Status.Fail)
|
||||
// {
|
||||
// _errorMsg = element.ErrorMsg;
|
||||
// st = Status.Fail;
|
||||
// }
|
||||
//
|
||||
// CurrentTask.RemoveAt(index);
|
||||
// index--;
|
||||
// FinishList.Add(element);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (FinishList.Count >= RawList.Count)
|
||||
// {
|
||||
// st = Status.Success;
|
||||
// }
|
||||
// else if (CurRunTask.Count < ParallelNum && _currentIndex < RawList.Count)
|
||||
// {
|
||||
// var num = ParallelNum - CurRunTask.Count;
|
||||
// for (var index = 0; index < num; index++)
|
||||
// {
|
||||
// if (_currentIndex < RawList.Count)
|
||||
// {
|
||||
// CurRunTask.Add(RawList[_currentIndex]);
|
||||
// _currentIndex += 1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
_currentIndex = 0;
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
base.Stop();
|
||||
_currentIndex = 0;
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
base.Clear();
|
||||
_currentIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
113
Core/Task/Collection/SequenceTaskCollection.cs
Normal file
113
Core/Task/Collection/SequenceTaskCollection.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
namespace NBC
|
||||
{
|
||||
public class SequenceTaskCollection : TaskCollection
|
||||
{
|
||||
private int _currentIndex;
|
||||
|
||||
public override string Info
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CurrentTask != null && CurrentTask.Count > 0) return CurrentTask[0].Info;
|
||||
|
||||
return TaskInfo;
|
||||
}
|
||||
}
|
||||
|
||||
protected override NTaskStatus RunTasksAndCheckIfDone()
|
||||
{
|
||||
var st = NTaskStatus.Running;
|
||||
|
||||
if (RawList.Count > 0)
|
||||
{
|
||||
if (CurRunTask.Count == 0 && _currentIndex < RawList.Count) CurRunTask.Add(RawList[_currentIndex]);
|
||||
|
||||
NTaskStatus curSt;
|
||||
do
|
||||
{
|
||||
var childTask = CurRunTask[0];
|
||||
curSt = childTask.Process();
|
||||
if (curSt >= NTaskStatus.Success)
|
||||
{
|
||||
if (FailBreak && curSt == NTaskStatus.Fail)
|
||||
{
|
||||
_errorMsg = childTask.ErrorMsg;
|
||||
st = NTaskStatus.Fail;
|
||||
break;
|
||||
}
|
||||
|
||||
FinishList.Add(childTask);
|
||||
CurRunTask.RemoveAt(0);
|
||||
_currentIndex++;
|
||||
if (_currentIndex < RawList.Count)
|
||||
CurRunTask.Add(RawList[_currentIndex]);
|
||||
}
|
||||
} while (curSt >= NTaskStatus.Success && CurRunTask.Count > 0);
|
||||
|
||||
if (FinishList.Count == RawList.Count)
|
||||
st = NTaskStatus.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
st = NTaskStatus.Success;
|
||||
}
|
||||
|
||||
|
||||
// if (RawList.Count > 0)
|
||||
// {
|
||||
// if (FinishList.Count == RawList.Count)
|
||||
// {
|
||||
// st = Status.Success;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (CurRunTask.Count == 0)
|
||||
// {
|
||||
// CurRunTask.Add(RawList[_currentIndex]);
|
||||
// }
|
||||
//
|
||||
// var childTask = CurRunTask[0];
|
||||
// var curSt = childTask.Process();
|
||||
//
|
||||
//
|
||||
// if (curSt >= Status.Success)
|
||||
// {
|
||||
// if (FailBreak && curSt == Status.Fail)
|
||||
// {
|
||||
// _errorMsg = childTask.ErrorMsg;
|
||||
// st = Status.Fail;
|
||||
// }
|
||||
//
|
||||
// FinishList.Add(childTask);
|
||||
// CurRunTask.RemoveAt(0);
|
||||
// _currentIndex++;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// st = Status.Success;
|
||||
// }
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
_currentIndex = 0;
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
base.Stop();
|
||||
_currentIndex = 0;
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
base.Clear();
|
||||
_currentIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
88
Core/Task/Collection/TaskCollection.cs
Normal file
88
Core/Task/Collection/TaskCollection.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public abstract class TaskCollection : NTask, ITaskCollection
|
||||
{
|
||||
protected readonly List<ITask> CurRunTask;
|
||||
protected readonly List<ITask> FinishList;
|
||||
protected readonly List<ITask> RawList;
|
||||
|
||||
|
||||
public TaskCollection(string taskInfo = "")
|
||||
{
|
||||
RawList = new List<ITask>();
|
||||
FinishList = new List<ITask>();
|
||||
CurRunTask = new List<ITask>();
|
||||
TaskInfo = taskInfo;
|
||||
Status = NTaskStatus.None;
|
||||
}
|
||||
|
||||
public virtual int Count => RawList.Count + FinishList.Count;
|
||||
|
||||
/// <summary>
|
||||
/// 任务失败中断任务链
|
||||
/// </summary>
|
||||
public virtual bool FailBreak { get; set; }
|
||||
|
||||
public List<ITask> CurrentTask => CurRunTask;
|
||||
|
||||
public override float Progress
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Status == NTaskStatus.Success) return 1;
|
||||
if (Status == NTaskStatus.None) return 0;
|
||||
var finishCount = FinishList.Count;
|
||||
for (var index = 0; index < CurRunTask.Count; index++)
|
||||
{
|
||||
var element = CurRunTask[index];
|
||||
finishCount += (int)element.Progress;
|
||||
}
|
||||
|
||||
return finishCount * 1f / RawList.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public ITaskCollection AddTask(ITask task)
|
||||
{
|
||||
RawList.Add(task);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
FinishList.Clear();
|
||||
CurrentTask.Clear();
|
||||
Status = NTaskStatus.None;
|
||||
for (int i = 0, len = RawList.Count; i < len; i++) RawList[i].Reset();
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
FinishList.Clear();
|
||||
Status = NTaskStatus.None;
|
||||
for (var i = 0; i < CurRunTask.Count; i++)
|
||||
{
|
||||
var task = CurrentTask[i];
|
||||
task.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public virtual void Clear()
|
||||
{
|
||||
FinishList.Clear();
|
||||
RawList.Clear();
|
||||
Status = NTaskStatus.None;
|
||||
}
|
||||
|
||||
protected override NTaskStatus OnProcess()
|
||||
{
|
||||
return RunTasksAndCheckIfDone();
|
||||
}
|
||||
|
||||
protected abstract NTaskStatus RunTasksAndCheckIfDone();
|
||||
}
|
||||
}
|
||||
10
Core/Task/Interface/IProcess.cs
Normal file
10
Core/Task/Interface/IProcess.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace NBC
|
||||
{
|
||||
/// <summary>
|
||||
/// 进度
|
||||
/// </summary>
|
||||
public interface IProcess
|
||||
{
|
||||
NTaskStatus Process();
|
||||
}
|
||||
}
|
||||
49
Core/Task/Interface/IRunner.cs
Normal file
49
Core/Task/Interface/IRunner.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
namespace NBC
|
||||
{
|
||||
public interface IRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否暂停
|
||||
/// </summary>
|
||||
bool IsPaused { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否已经终止了
|
||||
/// </summary>
|
||||
bool IsKilled { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前运行的任务数量
|
||||
/// </summary>
|
||||
int RunningTaskNum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 准备执行的任务数量
|
||||
/// </summary>
|
||||
int NeedRunTaskNum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 执行一个任务
|
||||
/// </summary>
|
||||
/// <param name="task">任务对象</param>
|
||||
void Run(ITask task);
|
||||
|
||||
void Process();
|
||||
|
||||
/// <summary>
|
||||
/// 停止任务
|
||||
/// </summary>
|
||||
/// <param name="task">任务对象</param>
|
||||
void StopTask(ITask task);
|
||||
|
||||
/// <summary>
|
||||
/// 停止所有任务
|
||||
/// </summary>
|
||||
void StopAllTask();
|
||||
|
||||
/// <summary>
|
||||
/// 终止任务
|
||||
/// </summary>
|
||||
void ShutDown();
|
||||
}
|
||||
}
|
||||
77
Core/Task/Interface/ITask.cs
Normal file
77
Core/Task/Interface/ITask.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public interface ITask : IProcess, IEnumerator
|
||||
{
|
||||
NTaskStatus Status { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前任务的信息
|
||||
/// </summary>
|
||||
string Info { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
string ErrorMsg { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前任务的进度
|
||||
/// </summary>
|
||||
float Progress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务正在执行
|
||||
/// </summary>
|
||||
bool IsRunning { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务是否执行完成
|
||||
/// </summary>
|
||||
bool IsDone { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 任务参数
|
||||
/// </summary>
|
||||
/// <param name="argsName"></param>
|
||||
object this[string argsName] { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 停止任务
|
||||
/// </summary>
|
||||
void Stop();
|
||||
|
||||
/// <summary>
|
||||
/// 任务开始回调
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
/// <param name="cover"></param>
|
||||
/// <returns></returns>
|
||||
ITask OnStarted(Action<ITask> callback, bool cover = false);
|
||||
|
||||
/// <summary>
|
||||
/// 任务执行回调
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
/// <param name="cover"></param>
|
||||
/// <returns></returns>
|
||||
ITask OnUpdated(Action<ITask> callback, bool cover = false);
|
||||
|
||||
/// <summary>
|
||||
/// 任务完成回调
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
/// <param name="cover"></param>
|
||||
/// <returns></returns>
|
||||
ITask OnCompleted(Action<ITask> callback, bool cover = false);
|
||||
|
||||
/// <summary>
|
||||
/// 运行任务
|
||||
/// </summary>
|
||||
/// <param name="runner">任务运行器</param>
|
||||
void Run(IRunner runner);
|
||||
}
|
||||
}
|
||||
24
Core/Task/Interface/ITaskCollection.cs
Normal file
24
Core/Task/Interface/ITaskCollection.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public interface ITaskCollection : ITask
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前运行的任务堆栈
|
||||
/// </summary>
|
||||
List<ITask> CurrentTask { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个任务
|
||||
/// </summary>
|
||||
/// <param name="task"></param>
|
||||
/// <returns></returns>
|
||||
ITaskCollection AddTask(ITask task);
|
||||
|
||||
/// <summary>
|
||||
/// 清理任务列表
|
||||
/// </summary>
|
||||
void Clear();
|
||||
}
|
||||
}
|
||||
7
Core/Task/Interface/ITaskRun.cs
Normal file
7
Core/Task/Interface/ITaskRun.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace NBC
|
||||
{
|
||||
public interface ITaskRun
|
||||
{
|
||||
void Run(IRunner runner);
|
||||
}
|
||||
}
|
||||
198
Core/Task/NTask.cs
Normal file
198
Core/Task/NTask.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public abstract class NTask : ITask
|
||||
{
|
||||
protected readonly Dictionary<string, object> _argsDic = new();
|
||||
protected string _errorMsg;
|
||||
protected float _progress;
|
||||
protected string TaskInfo;
|
||||
|
||||
public virtual string Info
|
||||
{
|
||||
get => TaskInfo;
|
||||
set => TaskInfo = value;
|
||||
}
|
||||
|
||||
public NTaskStatus Status { get; protected set; } = NTaskStatus.None;
|
||||
public virtual string ErrorMsg => _errorMsg;
|
||||
public virtual float Progress => _progress;
|
||||
|
||||
public virtual bool IsRunning => Status == NTaskStatus.Running;
|
||||
public virtual bool IsDone => Status == NTaskStatus.Success || Status == NTaskStatus.Fail;
|
||||
|
||||
public object this[string argsName]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_argsDic.TryGetValue(argsName, out var args)) return args;
|
||||
|
||||
return null;
|
||||
}
|
||||
set => _argsDic[argsName] = value;
|
||||
}
|
||||
|
||||
|
||||
public virtual void Stop()
|
||||
{
|
||||
Status = NTaskStatus.None;
|
||||
}
|
||||
|
||||
|
||||
public virtual void Run(IRunner runner)
|
||||
{
|
||||
Reset();
|
||||
runner?.Run(this);
|
||||
}
|
||||
|
||||
public NTaskStatus Process()
|
||||
{
|
||||
if (Status == NTaskStatus.None) Start();
|
||||
|
||||
Status = OnProcess();
|
||||
CallUpdateListener();
|
||||
if (Status == NTaskStatus.Success)
|
||||
{
|
||||
_progress = 1;
|
||||
CallCompleteListener(Status);
|
||||
}
|
||||
else if (Status == NTaskStatus.Fail)
|
||||
{
|
||||
_progress = 1;
|
||||
CallCompleteListener(Status);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
protected virtual void OnStart()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual NTaskStatus OnProcess()
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
protected void Finish()
|
||||
{
|
||||
_progress = 1;
|
||||
Status = NTaskStatus.Success;
|
||||
}
|
||||
|
||||
protected void Fail(string message)
|
||||
{
|
||||
_progress = 1;
|
||||
Status = NTaskStatus.Fail;
|
||||
_errorMsg = message;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Reset();
|
||||
Status = NTaskStatus.Running;
|
||||
_progress = 0;
|
||||
OnStart();
|
||||
CallStartListener();
|
||||
}
|
||||
|
||||
#region 事件
|
||||
|
||||
protected event Action<ITask> OnStartListener;
|
||||
protected event Action<ITask> OnCompleteListener;
|
||||
protected event Action<ITask> OnUpdateListener;
|
||||
|
||||
public ITask OnStarted(Action<ITask> callback, bool cover = false)
|
||||
{
|
||||
if (cover)
|
||||
OnStartListener = callback;
|
||||
else
|
||||
OnStartListener += callback;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ITask OnUpdated(Action<ITask> callback, bool cover = false)
|
||||
{
|
||||
if (cover)
|
||||
OnUpdateListener = callback;
|
||||
else
|
||||
OnUpdateListener += callback;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ITask OnCompleted(Action<ITask> callback, bool cover = false)
|
||||
{
|
||||
if (cover)
|
||||
OnCompleteListener = callback;
|
||||
else
|
||||
OnCompleteListener += callback;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void CallStartListener()
|
||||
{
|
||||
OnStartListener?.Invoke(this);
|
||||
}
|
||||
|
||||
protected void CallCompleteListener(NTaskStatus taskStatus)
|
||||
{
|
||||
OnCompleteListener?.Invoke(this);
|
||||
|
||||
_taskCompletionSource?.TrySetResult(null);
|
||||
}
|
||||
|
||||
protected void CallUpdateListener()
|
||||
{
|
||||
OnUpdateListener?.Invoke(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 异步编程相关
|
||||
|
||||
private TaskCompletionSource<object> _taskCompletionSource;
|
||||
|
||||
/// <summary>
|
||||
/// 异步操作任务
|
||||
/// </summary>
|
||||
public Task Task
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_taskCompletionSource == null)
|
||||
{
|
||||
_taskCompletionSource = new TaskCompletionSource<object>();
|
||||
if (IsDone)
|
||||
_taskCompletionSource.SetResult(null);
|
||||
}
|
||||
|
||||
return _taskCompletionSource.Task;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IEnumerator
|
||||
|
||||
bool IEnumerator.MoveNext()
|
||||
{
|
||||
return !IsDone;
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
Status = NTaskStatus.None;
|
||||
}
|
||||
|
||||
object IEnumerator.Current => null;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
25
Core/Task/NTaskStatus.cs
Normal file
25
Core/Task/NTaskStatus.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace NBC
|
||||
{
|
||||
public enum NTaskStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 任务还未执行
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 任务运行
|
||||
/// </summary>
|
||||
Running,
|
||||
|
||||
/// <summary>
|
||||
/// 任务执行成功
|
||||
/// </summary>
|
||||
Success,
|
||||
|
||||
/// <summary>
|
||||
/// 任务执行失败
|
||||
/// </summary>
|
||||
Fail
|
||||
}
|
||||
}
|
||||
18
Core/Task/Runner/FlushingOperation.cs
Normal file
18
Core/Task/Runner/FlushingOperation.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace NBC
|
||||
{
|
||||
/// <summary>
|
||||
/// 操作信息类
|
||||
/// </summary>
|
||||
public class FlushingOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否被终结
|
||||
/// </summary>
|
||||
public bool Kill;
|
||||
|
||||
/// <summary>
|
||||
/// 是否暂停
|
||||
/// </summary>
|
||||
public bool Paused;
|
||||
}
|
||||
}
|
||||
89
Core/Task/Runner/Runner.cs
Normal file
89
Core/Task/Runner/Runner.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public class Runner : IRunner
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前运行的任务
|
||||
/// </summary>
|
||||
protected readonly List<ITask> Coroutines = new();
|
||||
|
||||
/// <summary>
|
||||
/// 当前操作的信息
|
||||
/// </summary>
|
||||
protected readonly FlushingOperation FlushingOperation = new();
|
||||
|
||||
/// <summary>
|
||||
/// 准备要运行的任务
|
||||
/// </summary>
|
||||
protected readonly Queue<ITask> ReadyTask = new();
|
||||
|
||||
public bool IsPaused
|
||||
{
|
||||
get => FlushingOperation.Paused;
|
||||
set => FlushingOperation.Paused = value;
|
||||
}
|
||||
|
||||
public bool IsKilled => FlushingOperation.Kill;
|
||||
public int RunningTaskNum => Coroutines.Count;
|
||||
public int NeedRunTaskNum => ReadyTask.Count;
|
||||
|
||||
public virtual void Run(ITask task)
|
||||
{
|
||||
ReadyTask.Enqueue(task);
|
||||
}
|
||||
|
||||
public virtual void Process()
|
||||
{
|
||||
var count = ReadyTask.Count;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var task = ReadyTask.Dequeue();
|
||||
Coroutines.Add(task);
|
||||
}
|
||||
|
||||
if (Coroutines.Count < 1) return;
|
||||
|
||||
var index = 0;
|
||||
bool mustExit;
|
||||
do
|
||||
{
|
||||
var childTask = Coroutines[index];
|
||||
var st = childTask.Process();
|
||||
if (st >= NTaskStatus.Success)
|
||||
Coroutines.Remove(childTask);
|
||||
else
|
||||
index++;
|
||||
|
||||
mustExit = Coroutines.Count == 0 || index >= Coroutines.Count;
|
||||
} while (!mustExit);
|
||||
}
|
||||
|
||||
public virtual void StopTask(ITask task)
|
||||
{
|
||||
var index = Coroutines.IndexOf(task);
|
||||
if (index != -1)
|
||||
{
|
||||
var t = Coroutines[index];
|
||||
t.Stop();
|
||||
Coroutines.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void StopAllTask()
|
||||
{
|
||||
ReadyTask.Clear();
|
||||
for (var i = 0; i < Coroutines.Count; i++) Coroutines[i].Stop();
|
||||
|
||||
Coroutines.Clear();
|
||||
}
|
||||
|
||||
public virtual void ShutDown()
|
||||
{
|
||||
IsPaused = false;
|
||||
FlushingOperation.Kill = true;
|
||||
StopAllTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
77
Core/Task/Runner/RunnerProcess.cs
Normal file
77
Core/Task/Runner/RunnerProcess.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NBC
|
||||
{
|
||||
public class RunnerProcess : IProcess
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前运行的任务
|
||||
/// </summary>
|
||||
protected readonly List<ITask> Coroutines;
|
||||
|
||||
/// <summary>
|
||||
/// 当前操作的信息
|
||||
/// </summary>
|
||||
protected readonly FlushingOperation FlushingOperation;
|
||||
|
||||
/// <summary>
|
||||
/// 准备要运行的任务
|
||||
/// </summary>
|
||||
protected readonly Queue<ITask> ReadyTask;
|
||||
|
||||
/// <summary>
|
||||
/// 进程名称
|
||||
/// </summary>
|
||||
protected string Name;
|
||||
|
||||
public RunnerProcess(string name, List<ITask> coroutines, Queue<ITask> readyTask, FlushingOperation op)
|
||||
{
|
||||
Name = name;
|
||||
Coroutines = coroutines;
|
||||
ReadyTask = readyTask;
|
||||
FlushingOperation = op;
|
||||
}
|
||||
|
||||
public NTaskStatus Process()
|
||||
{
|
||||
var flag = false;
|
||||
if (FlushingOperation.Kill)
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var index = 0; index < ReadyTask.Count; index++)
|
||||
{
|
||||
// var task = ReadyTask[0];
|
||||
var task = ReadyTask.Dequeue();
|
||||
Coroutines.Add(task);
|
||||
// ReadyTask.RemoveAt(0);
|
||||
}
|
||||
|
||||
if (Coroutines.Count == 0 || FlushingOperation.Paused)
|
||||
{
|
||||
flag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = 0;
|
||||
var mustExit = false;
|
||||
do
|
||||
{
|
||||
var childTask = Coroutines[index];
|
||||
var st = childTask.Process();
|
||||
if (st >= NTaskStatus.Success)
|
||||
Coroutines.RemoveAt(index); //.splice(index, 1);
|
||||
else
|
||||
index++;
|
||||
|
||||
mustExit = Coroutines.Count == 0 || index >= Coroutines.Count;
|
||||
} while (!mustExit);
|
||||
}
|
||||
}
|
||||
|
||||
return flag ? NTaskStatus.Success : NTaskStatus.Running;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
Core/TaskRunner.cs
Normal file
54
Core/TaskRunner.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using NBC;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
/// <summary>
|
||||
/// 默认任务执行器
|
||||
/// </summary>
|
||||
public class TaskRunner : Runner
|
||||
{
|
||||
private static TaskRunner mUpdateRunner;
|
||||
public static TaskRunner Scheduler => mUpdateRunner ??= new TaskRunner();
|
||||
|
||||
private readonly List<IProcess> _updateRoutines = new List<IProcess>();
|
||||
|
||||
public event Action OnUpdate;
|
||||
|
||||
public TaskRunner()
|
||||
{
|
||||
Time.OnUpdate += Update;
|
||||
StartCoroutine(new RunnerProcess("TaskRunner", Coroutines, ReadyTask, FlushingOperation));
|
||||
}
|
||||
|
||||
private void StartCoroutine(IProcess process)
|
||||
{
|
||||
var routines = _updateRoutines;
|
||||
if (!routines.Contains(process))
|
||||
{
|
||||
routines.Add(process);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
ExecuteRoutines(_updateRoutines);
|
||||
OnUpdate?.Invoke();
|
||||
}
|
||||
|
||||
private void ExecuteRoutines(List<IProcess> arr)
|
||||
{
|
||||
if (arr != null && arr.Count > 0)
|
||||
{
|
||||
for (var index = 0; index < arr.Count; index++)
|
||||
{
|
||||
var task = arr[index];
|
||||
var st = task.Process();
|
||||
if (st == NTaskStatus.Success)
|
||||
{
|
||||
arr.RemoveAt(index);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
Core/Time.cs
Normal file
88
Core/Time.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
namespace ACBuildService;
|
||||
|
||||
public static class Time
|
||||
{
|
||||
public const long OneDay = 86400000;
|
||||
public const long Hour = 3600000;
|
||||
public const long Minute = 60000;
|
||||
|
||||
private static TimeInfo _timeInfo = new TimeInfo();
|
||||
|
||||
public static long Now => _timeInfo.Now();
|
||||
|
||||
public static long NowSeconds => Now / 1000;
|
||||
|
||||
public static DateTime DateTimeNow => DateTime.Now;
|
||||
|
||||
public static long FrameTime => _timeInfo.FrameTime;
|
||||
|
||||
public static event Action OnUpdate;
|
||||
public static event Action OnLateUpdate;
|
||||
|
||||
internal static void Awake()
|
||||
{
|
||||
}
|
||||
|
||||
internal static void Update()
|
||||
{
|
||||
_timeInfo.Update();
|
||||
OnUpdate?.Invoke();
|
||||
}
|
||||
|
||||
internal static void LateUpdate()
|
||||
{
|
||||
OnLateUpdate?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public class TimeInfo
|
||||
{
|
||||
private int timeZone;
|
||||
|
||||
public int TimeZone
|
||||
{
|
||||
get => timeZone;
|
||||
set
|
||||
{
|
||||
timeZone = value;
|
||||
dt = dt1970.AddHours(TimeZone);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly DateTime dt1970;
|
||||
private DateTime dt;
|
||||
|
||||
public long FrameTime;
|
||||
|
||||
public TimeInfo()
|
||||
{
|
||||
dt1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
FrameTime = Now();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
FrameTime = Now();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据时间戳获取时间
|
||||
/// </summary>
|
||||
public DateTime ToDateTime(long timeStamp)
|
||||
{
|
||||
return dt.AddTicks(timeStamp * 10000);
|
||||
}
|
||||
|
||||
// 线程安全
|
||||
public long Now()
|
||||
{
|
||||
return (DateTime.UtcNow.Ticks - dt1970.Ticks) / 10000;
|
||||
}
|
||||
|
||||
|
||||
public long Transition(DateTime d)
|
||||
{
|
||||
return (d.Ticks - dt.Ticks) / 10000;
|
||||
}
|
||||
}
|
||||
34
Db/DB.cs
Normal file
34
Db/DB.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using SqlSugar;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
public static class DB
|
||||
{
|
||||
public static SqlSugarClient Main { get; private set; }
|
||||
|
||||
public static void InitDb()
|
||||
{
|
||||
//创建数据库对象 (用法和EF Dappper一样通过new保证线程安全)
|
||||
Main = new SqlSugarClient(new ConnectionConfig()
|
||||
{
|
||||
ConnectionString = "datasource=data.db",
|
||||
DbType = DbType.Sqlite,
|
||||
IsAutoCloseConnection = true
|
||||
},
|
||||
db =>
|
||||
{
|
||||
// db.Aop.OnLogExecuting = (sql, pars) =>
|
||||
// {
|
||||
// //获取原生SQL推荐 5.1.4.63 性能OK
|
||||
// Console.WriteLine(UtilMethods.GetNativeSql(sql, pars));
|
||||
// };
|
||||
});
|
||||
|
||||
//建库
|
||||
Main.DbMaintenance.CreateDatabase();
|
||||
|
||||
//建表
|
||||
Main.CodeFirst.InitTables<VideoTable>();
|
||||
Main.CodeFirst.InitTables<DeviceTable>();
|
||||
}
|
||||
}
|
||||
38
Db/Tables/DeviceTable.cs
Normal file
38
Db/Tables/DeviceTable.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using SqlSugar;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
[SugarTable("device")]
|
||||
public class DeviceTable
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备id
|
||||
/// </summary>
|
||||
[SugarColumn(IsPrimaryKey = true)]
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 观看视频
|
||||
/// </summary>
|
||||
public int WatchId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备名字
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总观看时长
|
||||
/// </summary>
|
||||
public long TotalTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 今日观看时长
|
||||
/// </summary>
|
||||
public long TodayTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后更新时间,用于判定今日时长和跨天
|
||||
/// </summary>
|
||||
public DateTime LastTime { get; set; }
|
||||
}
|
||||
59
Db/Tables/VideoTable.cs
Normal file
59
Db/Tables/VideoTable.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using SqlSugar;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
|
||||
[SugarTable("video")]
|
||||
public class VideoTable
|
||||
{
|
||||
//数据是自增需要加上IsIdentity
|
||||
//数据库是主键需要加上IsPrimaryKey
|
||||
//注意:要完全和数据库一致2个属性
|
||||
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 源视频地址
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDataType = "text")]
|
||||
public string SourcePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 本地存储地址
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDataType = "text")]
|
||||
public string FilePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 作者
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDataType = "text")]
|
||||
public string AuthorName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标题
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDataType = "text")]
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 简介
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDataType = "text")]
|
||||
public string Desc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 视频时长
|
||||
/// </summary>
|
||||
[SugarColumn(ColumnDataType = "text")]
|
||||
public string Duration { get; set; }
|
||||
|
||||
public int Like { get; set; }
|
||||
public int Collect { get; set; }
|
||||
public int Message { get; set; }
|
||||
public int Share { get; set; }
|
||||
|
||||
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
11
Http/ErrorCode.cs
Normal file
11
Http/ErrorCode.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace ACBuildService;
|
||||
|
||||
public enum ErrorCode
|
||||
{
|
||||
/// <summary>
|
||||
/// 成功
|
||||
/// </summary>
|
||||
Success = 0,
|
||||
|
||||
ArgsError = 1,
|
||||
}
|
||||
24
Http/Extensions/DateTimeExtensions.cs
Normal file
24
Http/Extensions/DateTimeExtensions.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace ACBuildService;
|
||||
|
||||
public static class DateTimeExtensions
|
||||
{
|
||||
public static bool IsSameDay(this DateTime date1, DateTime date2)
|
||||
{
|
||||
return date1.Date == date2.Date;
|
||||
}
|
||||
|
||||
public static bool IsToday(this DateTime date)
|
||||
{
|
||||
return date.Date == DateTime.Today;
|
||||
}
|
||||
|
||||
public static bool IsYesterday(this DateTime date)
|
||||
{
|
||||
return date.Date == DateTime.Today.AddDays(-1);
|
||||
}
|
||||
|
||||
public static bool IsTomorrow(this DateTime date)
|
||||
{
|
||||
return date.Date == DateTime.Today.AddDays(1);
|
||||
}
|
||||
}
|
||||
25
Http/Extensions/FileNameExtensions.cs
Normal file
25
Http/Extensions/FileNameExtensions.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Text;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
|
||||
public static class FileNameExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 替换非法字符
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <returns></returns>
|
||||
public static string ReplaceInvalidCharacters(this string fileName)
|
||||
{
|
||||
var invalidChars = Path.GetInvalidFileNameChars();
|
||||
var replacedFileName = new StringBuilder();
|
||||
|
||||
foreach (var c in fileName)
|
||||
{
|
||||
replacedFileName.Append(!invalidChars.Contains(c) ? c : '#');
|
||||
}
|
||||
|
||||
return replacedFileName.ToString();
|
||||
}
|
||||
}
|
||||
49
Http/Extensions/HttpContextExtension.cs
Normal file
49
Http/Extensions/HttpContextExtension.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
public static class HttpContextExtension
|
||||
{
|
||||
public static async Task Error(this HttpContext context, ErrorCode code, string msg = "")
|
||||
{
|
||||
var res = new ResponseData<string>
|
||||
{
|
||||
Code = (int)code,
|
||||
Data = msg
|
||||
};
|
||||
await context.WriteJson(res);
|
||||
}
|
||||
|
||||
public static async Task Success(this HttpContext context)
|
||||
{
|
||||
var res = new ResponseData<string>
|
||||
{
|
||||
Code = 0,
|
||||
Data = string.Empty
|
||||
};
|
||||
await context.WriteJson(res);
|
||||
}
|
||||
|
||||
public static async Task Success<T>(this HttpContext context, T data)
|
||||
{
|
||||
var res = new ResponseData<T>
|
||||
{
|
||||
Code = 0,
|
||||
Data = data
|
||||
};
|
||||
await context.WriteJson(res);
|
||||
}
|
||||
|
||||
public static async Task WriteJson<T>(this HttpContext context, T obj)
|
||||
{
|
||||
context.Response.ContentType = "application/json";
|
||||
if (obj is string st)
|
||||
{
|
||||
await context.Response.WriteAsync(st);
|
||||
}
|
||||
else
|
||||
{
|
||||
await context.Response.WriteAsync(JSON.Serialize(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
75
Http/HttpService.cs
Normal file
75
Http/HttpService.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
public static class HttpService
|
||||
{
|
||||
public static WebApplication App { get; private set; }
|
||||
public static readonly string BaseRootPath = $"{AppContext.BaseDirectory}wwwroot/";
|
||||
|
||||
public static async Task Start()
|
||||
{
|
||||
var builder = WebApplication.CreateBuilder();
|
||||
|
||||
// 添加控制器服务
|
||||
builder.Services.AddControllers();
|
||||
|
||||
builder.WebHost.UseKestrel(options =>
|
||||
{
|
||||
//设置最大1G, 这里的单位是byte
|
||||
options.Limits.MaxRequestBodySize = int.MaxValue;
|
||||
|
||||
// HTTP
|
||||
if (ACBuildService.App.Settings.HttpPort > 0)
|
||||
{
|
||||
options.ListenAnyIP(ACBuildService.App.Settings.HttpPort);
|
||||
}
|
||||
})
|
||||
.ConfigureLogging(logging => { logging.SetMinimumLevel(LogLevel.Error); });
|
||||
|
||||
builder.Services.Configure<FormOptions>(x =>
|
||||
{
|
||||
x.ValueLengthLimit = int.MaxValue;
|
||||
x.MultipartBodyLengthLimit = int.MaxValue;
|
||||
});
|
||||
|
||||
var contentTypeProvider = new FileExtensionContentTypeProvider();
|
||||
contentTypeProvider.Mappings.Add(".bundle", "application/octet-stream");
|
||||
contentTypeProvider.Mappings.Add(".meta", "application/octet-stream");
|
||||
contentTypeProvider.Mappings.Add(".bytes", "application/octet-stream");
|
||||
|
||||
Log.Info($"wwwroot={BaseRootPath}");
|
||||
|
||||
App = builder.Build();
|
||||
|
||||
// 针对 files 文件夹配置
|
||||
var fileServerOptions = new FileServerOptions
|
||||
{
|
||||
RequestPath = "/files",
|
||||
EnableDirectoryBrowsing = true,
|
||||
FileProvider = new PhysicalFileProvider(BaseRootPath),
|
||||
StaticFileOptions =
|
||||
{
|
||||
ContentTypeProvider = contentTypeProvider
|
||||
}
|
||||
};
|
||||
|
||||
App.UseFileServer(fileServerOptions);
|
||||
|
||||
// 使用控制器路由
|
||||
App.MapControllers();
|
||||
|
||||
// 不再需要手动映射路由
|
||||
// App.MapGet("/", HttpHandler.Index);
|
||||
// App.MapPost("/api", HttpHandler.Api);
|
||||
|
||||
await App.StartAsync();
|
||||
Log.Info("http 服务启动成功");
|
||||
}
|
||||
}
|
||||
161
Http/Page/ApiController.cs
Normal file
161
Http/Page/ApiController.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
// Controllers/ApiController.cs
|
||||
|
||||
using ACBuildService.Filters;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace ACBuildService.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api")]
|
||||
[SignValidation]
|
||||
public class ApiController : NBControllerBase
|
||||
{
|
||||
#region 信息增删改
|
||||
|
||||
[HttpPost("list")]
|
||||
public async Task<IActionResult> List([FromForm] PageFormArgs data)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (data.Page < 1) data.Page = 1;
|
||||
if (data.PageSize < 1) data.PageSize = 50;
|
||||
|
||||
int totalCount = 0;
|
||||
|
||||
var list = DB.Main.Queryable<VideoTable>().ToPageList(data.Page, data.PageSize, ref totalCount);
|
||||
List<VideoRetData> retList = [];
|
||||
var retData = new PageListData<VideoRetData>
|
||||
{
|
||||
TotalCount = totalCount,
|
||||
Page = data.Page,
|
||||
List = retList,
|
||||
PageSize = data.PageSize
|
||||
};
|
||||
foreach (var video in list)
|
||||
{
|
||||
var r = new VideoRetData
|
||||
{
|
||||
Id = video.Id,
|
||||
FilePath = video.FilePath,
|
||||
Title = video.Title,
|
||||
Desc = video.Desc,
|
||||
Like = video.Like,
|
||||
Message = video.Message,
|
||||
Share = video.Share,
|
||||
Collect = video.Collect,
|
||||
AuthorName = video.AuthorName
|
||||
};
|
||||
retList.Add(r);
|
||||
}
|
||||
|
||||
|
||||
await Task.CompletedTask;
|
||||
|
||||
return Success(retData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return StatusCode(500, new { error = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("add")]
|
||||
public async Task<IActionResult> Add([FromForm] AddFormArgs data)
|
||||
{
|
||||
VideoDownload.Add(data.Text);
|
||||
await Task.CompletedTask;
|
||||
return Success();
|
||||
}
|
||||
|
||||
[HttpPost("edit")]
|
||||
public async Task<IActionResult> Edit([FromForm] EditFormArgs data)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
DB.Main.Updateable(new VideoTable()
|
||||
{
|
||||
Id = data.Id,
|
||||
Title = data.Title,
|
||||
Desc = data.Desc,
|
||||
Like = data.Like,
|
||||
Message = data.Message,
|
||||
Share = data.Share,
|
||||
Collect = data.Collect,
|
||||
AuthorName = data.AuthorName
|
||||
}).ExecuteCommand();
|
||||
return Success();
|
||||
}
|
||||
|
||||
|
||||
[HttpPost("remove")]
|
||||
public async Task<IActionResult> Remove([FromForm] IdFormArgs data)
|
||||
{
|
||||
var video = await DB.Main.Queryable<VideoTable>().FirstAsync(t => t.Id == data.Id);
|
||||
if (video != null)
|
||||
{
|
||||
//删除本地文件
|
||||
var filePath = FileUtil.GetVideoPath(video.FilePath);
|
||||
if (System.IO.File.Exists(filePath))
|
||||
{
|
||||
System.IO.File.Delete(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
await DB.Main.Deleteable<VideoTable>().Where(it => it.Id == data.Id).ExecuteCommandAsync();
|
||||
return Success();
|
||||
}
|
||||
|
||||
[HttpPost("info")]
|
||||
public async Task<IActionResult> Info()
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
|
||||
var list = DB.Main.Queryable<DeviceTable>().ToList();
|
||||
return Success(list);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 信息统计
|
||||
|
||||
[HttpPost("device")]
|
||||
public async Task<IActionResult> Device([FromForm] DeviceFormArgs data)
|
||||
{
|
||||
var now = DateTime.Now.AddDays(-1);
|
||||
var device = await DB.Main.Queryable<DeviceTable>().FirstAsync(t => t.Id == data.Device);
|
||||
if (device == null)
|
||||
{
|
||||
device = new DeviceTable
|
||||
{
|
||||
Id = data.Device,
|
||||
Name = data.DeviceName,
|
||||
WatchId = data.Id,
|
||||
TotalTime = 0,
|
||||
TodayTime = data.Time,
|
||||
LastTime = now
|
||||
};
|
||||
|
||||
await DB.Main.Insertable(device).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
if (!now.IsSameDay(device.LastTime))
|
||||
{
|
||||
device.TodayTime = data.Time; //重置今日时长
|
||||
}
|
||||
else
|
||||
{
|
||||
device.TodayTime += data.Time; //今日时长增加
|
||||
}
|
||||
|
||||
device.WatchId = data.Id;
|
||||
device.TotalTime += data.Time;
|
||||
|
||||
device.LastTime = now;
|
||||
|
||||
await DB.Main.Updateable(device).ExecuteCommandAsync();
|
||||
|
||||
return Success();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
68
Http/Page/Args.cs
Normal file
68
Http/Page/Args.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
namespace ACBuildService.Controllers;
|
||||
|
||||
public class BaseFormArgs
|
||||
{
|
||||
public string Sign { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class PageFormArgs : BaseFormArgs
|
||||
{
|
||||
public int Page { get; set; }
|
||||
public int PageSize { get; set; }
|
||||
}
|
||||
|
||||
public class AddFormArgs : BaseFormArgs
|
||||
{
|
||||
public string Text { get; set; }
|
||||
}
|
||||
|
||||
public class IdFormArgs : BaseFormArgs
|
||||
{
|
||||
public int Id { get; set; }
|
||||
}
|
||||
|
||||
public class EditFormArgs : VideoRetData
|
||||
{
|
||||
public string Sign { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class DeviceFormArgs : IdFormArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备id
|
||||
/// </summary>
|
||||
public string Device { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备名称
|
||||
/// </summary>
|
||||
public string DeviceName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 观看时长,离上次
|
||||
/// </summary>
|
||||
public long Time { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class PageListData<T>
|
||||
{
|
||||
public int TotalCount { get; set; }
|
||||
public int Page { get; set; }
|
||||
public int PageSize { get; set; }
|
||||
public List<T> List { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class VideoRetData
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string FilePath { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Desc { get; set; }
|
||||
public int Like { get; set; }
|
||||
public int Message { get; set; }
|
||||
public int Share { get; set; }
|
||||
public int Collect { get; set; }
|
||||
public string AuthorName { get; set; }
|
||||
}
|
||||
14
Http/Page/HomeController.cs
Normal file
14
Http/Page/HomeController.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace ACBuildService.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("/")]
|
||||
public class HomeController : NBControllerBase
|
||||
{
|
||||
[HttpGet("/")]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return Content("service running");
|
||||
}
|
||||
}
|
||||
36
Http/Page/NBControllerBase.cs
Normal file
36
Http/Page/NBControllerBase.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace ACBuildService.Controllers;
|
||||
|
||||
public abstract class NBControllerBase : ControllerBase
|
||||
{
|
||||
public OkObjectResult Error(ErrorCode code, string msg = "")
|
||||
{
|
||||
var res = new ResponseData<string>
|
||||
{
|
||||
Code = (int)code,
|
||||
Data = msg
|
||||
};
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
public OkObjectResult Success()
|
||||
{
|
||||
var res = new ResponseData<string>
|
||||
{
|
||||
Code = 0,
|
||||
Data = string.Empty
|
||||
};
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
public OkObjectResult Success<T>(T data)
|
||||
{
|
||||
var res = new ResponseData<T>
|
||||
{
|
||||
Code = 0,
|
||||
Data = data
|
||||
};
|
||||
return Ok(res);
|
||||
}
|
||||
}
|
||||
9
Http/ResponseData.cs
Normal file
9
Http/ResponseData.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
public class ResponseData<T>
|
||||
{
|
||||
[JsonPropertyName("code")] public int Code { get; set; }
|
||||
[JsonPropertyName("data")] public T Data { get; set; }
|
||||
}
|
||||
58
Http/SignValidationAttribute.cs
Normal file
58
Http/SignValidationAttribute.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
// Filters/SignValidationFilter.cs
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ACBuildService.Filters;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class SignValidationAttribute : Attribute, IAsyncActionFilter
|
||||
{
|
||||
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||
{
|
||||
// 检查请求是否包含 form-data
|
||||
if (context.HttpContext.Request.HasFormContentType)
|
||||
{
|
||||
var form = context.HttpContext.Request.Form;
|
||||
|
||||
// 尝试从表单中获取 Sign
|
||||
if (form.TryGetValue("Sign", out var signValue))
|
||||
{
|
||||
if (!signValue.ToString().Equals(App.Settings.Password))
|
||||
{
|
||||
// 验证失败,直接返回错误
|
||||
context.Result = new ObjectResult(new ResponseData<string>
|
||||
{
|
||||
Code = (int)ErrorCode.ArgsError,
|
||||
Data = "sign is error"
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 没有 Sign 字段
|
||||
context.Result = new ObjectResult(new ResponseData<string>
|
||||
{
|
||||
Code = (int)ErrorCode.ArgsError,
|
||||
Data = "sign is null"
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Result = new ObjectResult(new ResponseData<string>
|
||||
{
|
||||
Code = (int)ErrorCode.ArgsError,
|
||||
Data = "请求格式必须是 form-data"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证通过,继续执行 Action
|
||||
await next();
|
||||
}
|
||||
}
|
||||
64
JSON/JSON.cs
Normal file
64
JSON/JSON.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020-2023 BobSong, nobug.cn Co.,Ltd and Contributors
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
/// <summary>
|
||||
/// JSON 静态帮助类
|
||||
/// </summary>
|
||||
public static class JSON
|
||||
{
|
||||
/// <summary>
|
||||
/// 序列化对象
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string Serialize(object value)
|
||||
{
|
||||
return JsonSerializer.Serialize(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化字符串
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="json"></param>
|
||||
/// <returns></returns>
|
||||
public static T Deserialize<T>(string json)
|
||||
{
|
||||
return JsonSerializer.Deserialize<T>(json);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化字符串
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="json"></param>
|
||||
/// <returns></returns>
|
||||
public static object Deserialize<T>(Type type, string json)
|
||||
{
|
||||
return JsonSerializer.Deserialize(json, type);
|
||||
}
|
||||
}
|
||||
17
Log/ILog.cs
Normal file
17
Log/ILog.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace ACBuildService;
|
||||
|
||||
public interface ILog
|
||||
{
|
||||
void Info(string message);
|
||||
void Info(string message, params object[] args);
|
||||
void Warning(string message);
|
||||
void Warning(string message, params object[] args);
|
||||
void Error(string message);
|
||||
void Error(string message, params object[] args);
|
||||
void Trace(string message);
|
||||
void Trace(string message, params object[] args);
|
||||
void Debug(string message);
|
||||
void Debug(string message, params object[] args);
|
||||
void Fatal(string message);
|
||||
void Fatal(string message, params object[] args);
|
||||
}
|
||||
165
Log/Log.cs
Normal file
165
Log/Log.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
/// <summary>
|
||||
/// 全局日志静态类
|
||||
/// </summary>
|
||||
public static class Log
|
||||
{
|
||||
private static ILog _log;
|
||||
|
||||
private static Func<ILog> _createLogger = NLogger.CreateInstance;
|
||||
|
||||
public static readonly List<LogInfo> LogList = new List<LogInfo>();
|
||||
|
||||
public static Func<ILog> CreateLogger
|
||||
{
|
||||
get => _createLogger;
|
||||
set
|
||||
{
|
||||
_createLogger = value;
|
||||
_log = _createLogger();
|
||||
}
|
||||
}
|
||||
|
||||
static Log()
|
||||
{
|
||||
_log = CreateLogger();
|
||||
}
|
||||
|
||||
#region Info
|
||||
|
||||
public static void Info(string msg)
|
||||
{
|
||||
_log.Info(msg);
|
||||
AddLog(msg);
|
||||
}
|
||||
|
||||
public static void Info(ref DefaultInterpolatedStringHandler message)
|
||||
{
|
||||
var msg = message.ToStringAndClear();
|
||||
_log.Info(msg);
|
||||
AddLog(msg);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Warning
|
||||
|
||||
public static void Warning(string msg)
|
||||
{
|
||||
_log.Warning(msg);
|
||||
AddLog(msg, 1);
|
||||
}
|
||||
|
||||
public static void Warning(ref DefaultInterpolatedStringHandler message)
|
||||
{
|
||||
var msg = message.ToStringAndClear();
|
||||
_log.Warning(msg);
|
||||
AddLog(msg, 1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Error
|
||||
|
||||
public static void Error(string msg)
|
||||
{
|
||||
_log.Error(msg);
|
||||
AddLog(msg, 2);
|
||||
}
|
||||
|
||||
public static void Error(Exception msg)
|
||||
{
|
||||
_log.Error(msg.ToString());
|
||||
AddLog(msg.ToString(), 2);
|
||||
}
|
||||
|
||||
public static void Error(ref DefaultInterpolatedStringHandler message)
|
||||
{
|
||||
var msg = message.ToStringAndClear();
|
||||
_log.Error(msg);
|
||||
AddLog(msg, 2);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Trace
|
||||
|
||||
public static void Trace(string msg)
|
||||
{
|
||||
_log.Trace(msg);
|
||||
AddLog(msg, 4);
|
||||
}
|
||||
|
||||
public static void Trace(ref DefaultInterpolatedStringHandler message)
|
||||
{
|
||||
_log.Trace(message.ToStringAndClear());
|
||||
AddLog(message.ToStringAndClear(), 4);
|
||||
}
|
||||
|
||||
public static void TraceInfo(string msg)
|
||||
{
|
||||
_log.Trace(msg);
|
||||
AddLog(msg, 4);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Debug
|
||||
|
||||
public static void Debug(string msg)
|
||||
{
|
||||
_log.Debug(msg);
|
||||
AddLog(msg, 4);
|
||||
}
|
||||
|
||||
public static void Debug(ref DefaultInterpolatedStringHandler message)
|
||||
{
|
||||
_log.Debug(message.ToStringAndClear());
|
||||
AddLog(message.ToStringAndClear(), 4);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fatal
|
||||
|
||||
public static void Fatal(string message)
|
||||
{
|
||||
_log.Fatal(message);
|
||||
AddLog(message, 5);
|
||||
}
|
||||
|
||||
public static void Fatal(string message, params object[] args)
|
||||
{
|
||||
_log.Fatal(message, args);
|
||||
AddLog(string.Format(message, args), 5);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static void AddLog(string msg, int level = 0)
|
||||
{
|
||||
if (LogList.Count > 1000)
|
||||
{
|
||||
LogList.RemoveAt(0);
|
||||
}
|
||||
|
||||
LogInfo log = new LogInfo
|
||||
{
|
||||
message = msg,
|
||||
level = level,
|
||||
timestamp = DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss.fff")
|
||||
};
|
||||
LogList.Add(log);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class LogInfo
|
||||
{
|
||||
public string timestamp { get; set; }
|
||||
public int level { get; set; }
|
||||
public string message { get; set; }
|
||||
}
|
||||
249
Log/NLog.cs
Normal file
249
Log/NLog.cs
Normal file
@@ -0,0 +1,249 @@
|
||||
using NLog;
|
||||
using NLog.Conditions;
|
||||
using NLog.Config;
|
||||
using NLog.Targets;
|
||||
using NLog.Targets.Wrappers;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
public class NLogger : ILog
|
||||
{
|
||||
private readonly Logger _log;
|
||||
|
||||
public static ILog CreateInstance()
|
||||
{
|
||||
return new NLogger();
|
||||
}
|
||||
|
||||
public NLogger()
|
||||
{
|
||||
var path = "NLog.config";
|
||||
if (File.Exists(path))
|
||||
{
|
||||
LogManager.Configuration = new XmlLoggingConfiguration(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
var config = new LoggingConfiguration();
|
||||
|
||||
var serverDebug = new AsyncTargetWrapper();
|
||||
serverDebug.WrappedTarget = new FileTarget("serverDebug")
|
||||
{
|
||||
OpenFileCacheTimeout = 10,
|
||||
Layout =
|
||||
"${longdate} | ${message} ${onexception:${exception:format=message} ${newline} ${stacktrace} ${newline}",
|
||||
FileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.${date:format=yyyyMMddHH}.Debug.log",
|
||||
ArchiveFileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.{#}.Debug.log",
|
||||
ArchiveNumbering = ArchiveNumberingMode.Date,
|
||||
ArchiveEvery = FileArchivePeriod.Hour,
|
||||
ArchiveDateFormat = "yyyyMMddHH",
|
||||
KeepFileOpen = true,
|
||||
};
|
||||
|
||||
var serverInfo = new AsyncTargetWrapper();
|
||||
serverInfo.WrappedTarget = new FileTarget("serverInfo")
|
||||
{
|
||||
OpenFileCacheTimeout = 10,
|
||||
Layout =
|
||||
"${longdate} ${message}",
|
||||
FileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.${date:format=yyyyMMddHH}.Info.log",
|
||||
ArchiveFileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.{#}.Info.log",
|
||||
ArchiveNumbering = ArchiveNumberingMode.Date,
|
||||
ArchiveEvery = FileArchivePeriod.Hour,
|
||||
ArchiveDateFormat = "yyyyMMddHH",
|
||||
KeepFileOpen = true,
|
||||
};
|
||||
|
||||
var serverError = new AsyncTargetWrapper();
|
||||
serverError.WrappedTarget = new FileTarget("serverError")
|
||||
{
|
||||
OpenFileCacheTimeout = 10,
|
||||
Layout =
|
||||
"${longdate} | ${message} ${onexception:${exception:format=message} ${newline} ${stacktrace} ${newline}",
|
||||
FileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.${date:format=yyyyMMddHH}.Error.log",
|
||||
ArchiveFileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.{#}.Error.log",
|
||||
ArchiveNumbering = ArchiveNumberingMode.Date,
|
||||
ArchiveEvery = FileArchivePeriod.Hour,
|
||||
ArchiveDateFormat = "yyyyMMddHH",
|
||||
KeepFileOpen = true,
|
||||
};
|
||||
|
||||
|
||||
var serverWarn = new AsyncTargetWrapper();
|
||||
serverWarn.WrappedTarget = new FileTarget("serverWarn")
|
||||
{
|
||||
OpenFileCacheTimeout = 10,
|
||||
Layout =
|
||||
"${longdate} ${message}",
|
||||
FileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.${date:format=yyyyMMddHH}.Warn.log",
|
||||
ArchiveFileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.{#}.Warn.log",
|
||||
ArchiveNumbering = ArchiveNumberingMode.Date,
|
||||
ArchiveEvery = FileArchivePeriod.Hour,
|
||||
ArchiveDateFormat = "yyyyMMddHH",
|
||||
KeepFileOpen = true,
|
||||
};
|
||||
|
||||
var serverFatal = new AsyncTargetWrapper();
|
||||
serverFatal.WrappedTarget = new FileTarget("serverFatal")
|
||||
{
|
||||
OpenFileCacheTimeout = 10,
|
||||
Layout =
|
||||
"${longdate} | ${message} ${onexception:${exception:format=message} ${newline} ${stacktrace} ${newline}",
|
||||
FileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.${date:format=yyyyMMddHH}.Fatal.log",
|
||||
ArchiveFileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.{#}.Fatal.log",
|
||||
ArchiveNumbering = ArchiveNumberingMode.Date,
|
||||
ArchiveEvery = FileArchivePeriod.Hour,
|
||||
ArchiveDateFormat = "yyyyMMddHH",
|
||||
KeepFileOpen = true,
|
||||
};
|
||||
|
||||
var serverTrace = new AsyncTargetWrapper();
|
||||
serverTrace.WrappedTarget = new FileTarget("serverTrace")
|
||||
{
|
||||
OpenFileCacheTimeout = 10,
|
||||
Layout =
|
||||
"${longdate} | ${message} ${onexception:${exception:format=message} ${newline} ${stacktrace} ${newline}",
|
||||
FileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.${date:format=yyyyMMddHH}.Trace.log",
|
||||
ArchiveFileName = "${basedir}/Logs/${logger}.${var:appIdFormat}.{#}.Trace.log",
|
||||
ArchiveNumbering = ArchiveNumberingMode.Date,
|
||||
ArchiveEvery = FileArchivePeriod.Hour,
|
||||
ArchiveDateFormat = "yyyyMMddHH",
|
||||
KeepFileOpen = true,
|
||||
};
|
||||
|
||||
var consoleTarget = new ColoredConsoleTarget()
|
||||
{
|
||||
Layout = "[${date:format=HH\\:mm\\:ss}]:${message} ${exception:format=message}"
|
||||
};
|
||||
|
||||
var highlightRuleDebug = new ConsoleRowHighlightingRule
|
||||
{
|
||||
Condition = ConditionParser.ParseExpression("level == LogLevel.Debug"),
|
||||
ForegroundColor = ConsoleOutputColor.Gray
|
||||
};
|
||||
consoleTarget.RowHighlightingRules.Add(highlightRuleDebug);
|
||||
|
||||
var highlightRuleTrace = new ConsoleRowHighlightingRule
|
||||
{
|
||||
Condition = ConditionParser.ParseExpression("level == LogLevel.Trace"),
|
||||
ForegroundColor = ConsoleOutputColor.DarkGray
|
||||
};
|
||||
consoleTarget.RowHighlightingRules.Add(highlightRuleTrace);
|
||||
|
||||
var highlightRuleWarn = new ConsoleRowHighlightingRule
|
||||
{
|
||||
Condition = ConditionParser.ParseExpression("level == LogLevel.Warn"),
|
||||
ForegroundColor = ConsoleOutputColor.Yellow
|
||||
};
|
||||
consoleTarget.RowHighlightingRules.Add(highlightRuleWarn);
|
||||
|
||||
var highlightRuleError = new ConsoleRowHighlightingRule
|
||||
{
|
||||
Condition = ConditionParser.ParseExpression("level == LogLevel.Error"),
|
||||
ForegroundColor = ConsoleOutputColor.Red
|
||||
};
|
||||
consoleTarget.RowHighlightingRules.Add(highlightRuleError);
|
||||
|
||||
var highlightRuleFatal = new ConsoleRowHighlightingRule
|
||||
{
|
||||
Condition = ConditionParser.ParseExpression("level == LogLevel.Fatal"),
|
||||
ForegroundColor = ConsoleOutputColor.Red,
|
||||
BackgroundColor = ConsoleOutputColor.White
|
||||
};
|
||||
consoleTarget.RowHighlightingRules.Add(highlightRuleFatal);
|
||||
|
||||
|
||||
config.AddRule(LogLevel.Trace, LogLevel.Trace, serverTrace);
|
||||
config.AddRule(LogLevel.Error, LogLevel.Error, serverError);
|
||||
config.AddRule(LogLevel.Warn, LogLevel.Warn, serverWarn);
|
||||
config.AddRule(LogLevel.Debug, LogLevel.Debug, serverDebug);
|
||||
config.AddRule(LogLevel.Fatal, LogLevel.Fatal, serverFatal);
|
||||
config.AddRule(LogLevel.Info, LogLevel.Info, serverInfo);
|
||||
|
||||
//console
|
||||
if (App.Settings.Debug)
|
||||
{
|
||||
config.AddRule(LogLevel.Trace, LogLevel.Fatal, consoleTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
config.AddRule(LogLevel.Trace, LogLevel.Trace, consoleTarget);
|
||||
config.AddRule(LogLevel.Error, LogLevel.Error, consoleTarget);
|
||||
config.AddRule(LogLevel.Warn, LogLevel.Warn, consoleTarget);
|
||||
config.AddRule(LogLevel.Debug, LogLevel.Debug, consoleTarget);
|
||||
config.AddRule(LogLevel.Fatal, LogLevel.Fatal, consoleTarget);
|
||||
}
|
||||
|
||||
LogManager.Configuration = config;
|
||||
}
|
||||
|
||||
|
||||
LogManager.Configuration.Variables["appIdFormat"] = $"1";
|
||||
|
||||
LogManager.Configuration.Variables["currentDir"] = Environment.CurrentDirectory;
|
||||
_log = LogManager.GetLogger("nbc");
|
||||
}
|
||||
|
||||
|
||||
public void Info(string message)
|
||||
{
|
||||
_log.Info(message);
|
||||
}
|
||||
|
||||
public void Info(string message, params object[] args)
|
||||
{
|
||||
_log.Info(message, args);
|
||||
}
|
||||
|
||||
|
||||
public void Warning(string message)
|
||||
{
|
||||
_log.Warn(message);
|
||||
}
|
||||
|
||||
public void Warning(string message, params object[] args)
|
||||
{
|
||||
_log.Warn(message, args);
|
||||
}
|
||||
|
||||
public void Error(string message)
|
||||
{
|
||||
_log.Error(message);
|
||||
}
|
||||
|
||||
public void Error(string message, params object[] args)
|
||||
{
|
||||
_log.Error(message, args);
|
||||
}
|
||||
|
||||
public void Trace(string message)
|
||||
{
|
||||
_log.Trace(message);
|
||||
}
|
||||
|
||||
public void Trace(string message, params object[] args)
|
||||
{
|
||||
_log.Trace(message, args);
|
||||
}
|
||||
|
||||
public void Debug(string message)
|
||||
{
|
||||
_log.Debug(message);
|
||||
}
|
||||
|
||||
|
||||
public void Debug(string message, params object[] args)
|
||||
{
|
||||
_log.Debug(message, args);
|
||||
}
|
||||
|
||||
public void Fatal(string message)
|
||||
{
|
||||
_log.Fatal(message);
|
||||
}
|
||||
|
||||
public void Fatal(string message, params object[] args)
|
||||
{
|
||||
_log.Fatal(message, args);
|
||||
}
|
||||
}
|
||||
60
Program.cs
Normal file
60
Program.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System.Diagnostics;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ACBuildService;
|
||||
|
||||
public class Program
|
||||
{
|
||||
private static volatile Task _loopTask;
|
||||
private static volatile Task _shutDownTask;
|
||||
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
App.Init();
|
||||
Test();
|
||||
await HttpService.Start();
|
||||
ExitHandle();
|
||||
_loopTask = EnterAsync();
|
||||
await _loopTask;
|
||||
}
|
||||
|
||||
private static async Task EnterAsync()
|
||||
{
|
||||
while (App.Running)
|
||||
{
|
||||
await Task.Delay(10);
|
||||
App.Update();
|
||||
App.LateUpdate();
|
||||
}
|
||||
|
||||
Log.Info("Stop");
|
||||
}
|
||||
|
||||
private static void ExitHandle()
|
||||
{
|
||||
//退出监听
|
||||
AppDomain.CurrentDomain.ProcessExit += (_, _) => { ServerExitConfirm(); };
|
||||
//Fetal异常监听
|
||||
AppDomain.CurrentDomain.UnhandledException += (_, e) => { ServerExitConfirm(); };
|
||||
//ctrl+c
|
||||
Console.CancelKeyPress += (_, _) => { ServerExitConfirm(); };
|
||||
}
|
||||
|
||||
private static void ServerExitConfirm()
|
||||
{
|
||||
Log.Info("开始执行退出程序");
|
||||
_shutDownTask = Task.Run(() =>
|
||||
{
|
||||
App.Running = false;
|
||||
_loopTask?.Wait();
|
||||
Console.WriteLine("退出完成");
|
||||
Process.GetCurrentProcess().Kill();
|
||||
});
|
||||
_shutDownTask.Wait();
|
||||
}
|
||||
|
||||
|
||||
private static void Test()
|
||||
{
|
||||
}
|
||||
}
|
||||
27
Utils.cs
Normal file
27
Utils.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
namespace ACBuildService;
|
||||
|
||||
public class Utils
|
||||
{
|
||||
public static string GetFileSizeTitle(long length)
|
||||
{
|
||||
if (length < 1024)
|
||||
{
|
||||
return length + "B";
|
||||
}
|
||||
|
||||
length /= 1024;
|
||||
|
||||
if (length < 1024)
|
||||
{
|
||||
return (length * 100 / 100) + "KB";
|
||||
}
|
||||
|
||||
length /= 1024;
|
||||
if (length < 1024)
|
||||
{
|
||||
return (length * 100 / 100.0f) + "MB";
|
||||
}
|
||||
|
||||
return ((length / 1024 * 100) / 100.0f) + "GB";
|
||||
}
|
||||
}
|
||||
44
Utils/FileUtil.cs
Normal file
44
Utils/FileUtil.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
namespace ACBuildService;
|
||||
|
||||
public class FileUtil
|
||||
{
|
||||
public static readonly string BaseRootPath = $"{AppContext.BaseDirectory}wwwroot/";
|
||||
|
||||
public static string GetFileSizeTitle(long length)
|
||||
{
|
||||
if (length < 1024)
|
||||
{
|
||||
return length + "B";
|
||||
}
|
||||
|
||||
length /= 1024;
|
||||
|
||||
if (length < 1024)
|
||||
{
|
||||
return (length * 100 / 100) + "KB";
|
||||
}
|
||||
|
||||
length /= 1024;
|
||||
if (length < 1024)
|
||||
{
|
||||
return (length * 100 / 100.0f) + "MB";
|
||||
}
|
||||
|
||||
return ((length / 1024 * 100) / 100.0f) + "GB";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得文件夹下所有的文件(类库调用)
|
||||
/// </summary>
|
||||
/// <param name="dir"></param>
|
||||
/// <returns></returns>
|
||||
public static FileInfo[] GetAllFileInfo(DirectoryInfo dir)
|
||||
{
|
||||
return dir.GetFiles(".", SearchOption.AllDirectories);
|
||||
}
|
||||
|
||||
public static string GetVideoPath(string fileName)
|
||||
{
|
||||
return Path.Combine(BaseRootPath, fileName);
|
||||
}
|
||||
}
|
||||
50
Utils/HttpHelper.cs
Normal file
50
Utils/HttpHelper.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
public static class HttpHelper
|
||||
{
|
||||
private static readonly HttpClient _httpClient = new HttpClient();
|
||||
|
||||
public static async Task<string> GetAsync(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpResponseMessage response = await _httpClient.GetAsync(url);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// 使用 UTF-8 编码读取响应内容
|
||||
byte[] byteArray = await response.Content.ReadAsByteArrayAsync();
|
||||
return Encoding.UTF8.GetString(byteArray);
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
// 处理请求异常
|
||||
Console.WriteLine($"Request error: {e.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> PostAsync<T>(string url, T data)
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = JsonSerializer.Serialize(data);
|
||||
StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
|
||||
HttpResponseMessage response = await _httpClient.PostAsync(url, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// 使用 UTF-8 编码读取响应内容
|
||||
byte[] byteArray = await response.Content.ReadAsByteArrayAsync();
|
||||
return Encoding.UTF8.GetString(byteArray);
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
// 处理请求异常
|
||||
Console.WriteLine($"Request error: {e.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
296
VideoDownload/DouyinShareRouterData.cs
Normal file
296
VideoDownload/DouyinShareRouterData.cs
Normal file
@@ -0,0 +1,296 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
/// <summary>
|
||||
/// 抖音 分享文本中的视频数据
|
||||
/// </summary>
|
||||
public class DouYinShareRouterData
|
||||
{
|
||||
[JsonProperty("loaderData")] public LoaderData LoaderData { get; set; }
|
||||
}
|
||||
|
||||
public class LoaderData
|
||||
{
|
||||
[JsonProperty("video_(id)/page")] public VideoIdPage VideoIdPage { get; set; }
|
||||
}
|
||||
|
||||
public class VideoIdPage
|
||||
{
|
||||
[JsonProperty("isAutoOpenApp")] public bool IsAutoOpenApp { get; set; }
|
||||
|
||||
[JsonProperty("appName")] public string AppName { get; set; }
|
||||
|
||||
[JsonProperty("query")] public Query Query { get; set; }
|
||||
|
||||
[JsonProperty("isSpider")] public bool IsSpider { get; set; }
|
||||
|
||||
[JsonProperty("ua")] public string Ua { get; set; }
|
||||
|
||||
[JsonProperty("isVideoOptimize")] public bool IsVideoOptimize { get; set; }
|
||||
|
||||
[JsonProperty("commonContext")] public CommonContext CommonContext { get; set; }
|
||||
|
||||
[JsonProperty("itemId")] public string ItemId { get; set; }
|
||||
|
||||
[JsonProperty("webId")] public string WebId { get; set; }
|
||||
|
||||
[JsonProperty("renderInSSR")] public long RenderInSsr { get; set; }
|
||||
|
||||
[JsonProperty("host")] public string Host { get; set; }
|
||||
|
||||
[JsonProperty("videoInfoRes")] public VideoInfoRes VideoInfoRes { get; set; }
|
||||
|
||||
[JsonProperty("darkModeAdaptation")] public bool DarkModeAdaptation { get; set; }
|
||||
|
||||
[JsonProperty("lastPath")] public string LastPath { get; set; }
|
||||
|
||||
[JsonProperty("isNotSupportWebp")] public bool IsNotSupportWebp { get; set; }
|
||||
|
||||
[JsonProperty("serverToken")] public string ServerToken { get; set; }
|
||||
}
|
||||
|
||||
public class CommonContext
|
||||
{
|
||||
[JsonProperty("webId")] public string WebId { get; set; }
|
||||
|
||||
[JsonProperty("renderInSSR")] public long RenderInSsr { get; set; }
|
||||
|
||||
[JsonProperty("appName")] public string AppName { get; set; }
|
||||
|
||||
[JsonProperty("query")] public Query Query { get; set; }
|
||||
|
||||
[JsonProperty("host")] public string Host { get; set; }
|
||||
|
||||
[JsonProperty("isSpider")] public bool IsSpider { get; set; }
|
||||
|
||||
[JsonProperty("lastPath")] public string LastPath { get; set; }
|
||||
|
||||
[JsonProperty("isNotSupportWebp")] public bool IsNotSupportWebp { get; set; }
|
||||
|
||||
[JsonProperty("ua")] public string Ua { get; set; }
|
||||
}
|
||||
|
||||
public class Query
|
||||
{
|
||||
[JsonProperty("titleType")] public string TitleType { get; set; }
|
||||
|
||||
[JsonProperty("iid")] public string Iid { get; set; }
|
||||
|
||||
[JsonProperty("u_code")] public string UCode { get; set; }
|
||||
|
||||
[JsonProperty("from_ssr")] public long FromSsr { get; set; }
|
||||
|
||||
[JsonProperty("mid")] public string Mid { get; set; }
|
||||
|
||||
[JsonProperty("share_sign")] public string ShareSign { get; set; }
|
||||
|
||||
[JsonProperty("with_sec_did")] public long WithSecDid { get; set; }
|
||||
|
||||
[JsonProperty("from_aid")] public long FromAid { get; set; }
|
||||
|
||||
[JsonProperty("from")] public string From { get; set; }
|
||||
|
||||
[JsonProperty("region")] public string Region { get; set; }
|
||||
|
||||
[JsonProperty("did")] public string Did { get; set; }
|
||||
|
||||
[JsonProperty("share_version")] public long ShareVersion { get; set; }
|
||||
|
||||
[JsonProperty("ts")] public long Ts { get; set; }
|
||||
}
|
||||
|
||||
public class VideoInfoRes
|
||||
{
|
||||
[JsonProperty("status_code")] public long StatusCode { get; set; }
|
||||
|
||||
[JsonProperty("filter_list")] public List<object> FilterList { get; set; }
|
||||
|
||||
[JsonProperty("item_list")] public List<ItemList> ItemList { get; set; }
|
||||
|
||||
[JsonProperty("extra")] public Extra Extra { get; set; }
|
||||
}
|
||||
|
||||
public class Extra
|
||||
{
|
||||
[JsonProperty("now")] public long Now { get; set; }
|
||||
}
|
||||
|
||||
public class ItemList
|
||||
{
|
||||
[JsonProperty("video")] public Video Video { get; set; }
|
||||
|
||||
[JsonProperty("music")] public Music Music { get; set; }
|
||||
|
||||
[JsonProperty("create_time")] public long CreateTime { get; set; }
|
||||
|
||||
[JsonProperty("author")] public Author Author { get; set; }
|
||||
|
||||
[JsonProperty("risk_infos")] public RiskInfos RiskInfos { get; set; }
|
||||
|
||||
[JsonProperty("mix_info")] public MixInfo MixInfo { get; set; }
|
||||
|
||||
[JsonProperty("aweme_id")] public string AwemeId { get; set; }
|
||||
|
||||
[JsonProperty("group_id_str")] public string GroupIdStr { get; set; }
|
||||
|
||||
[JsonProperty("text_extra")] public List<TextExtra> TextExtra { get; set; }
|
||||
|
||||
[JsonProperty("aweme_type")] public long AwemeType { get; set; }
|
||||
|
||||
[JsonProperty("desc")] public string Desc { get; set; }
|
||||
|
||||
[JsonProperty("statistics")] public Statistics Statistics { get; set; }
|
||||
}
|
||||
|
||||
public class Author
|
||||
{
|
||||
[JsonProperty("avatar_medium")] public AvatarMedium AvatarMedium { get; set; }
|
||||
|
||||
[JsonProperty("unique_id")] public string UniqueId { get; set; }
|
||||
|
||||
[JsonProperty("sec_uid")] public string SecUid { get; set; }
|
||||
|
||||
[JsonProperty("signature")] public string Signature { get; set; }
|
||||
|
||||
[JsonProperty("mplatform_followers_count")]
|
||||
public long MplatformFollowersCount { get; set; }
|
||||
|
||||
[JsonProperty("avatar_thumb")] public AvatarMedium AvatarThumb { get; set; }
|
||||
|
||||
[JsonProperty("follow_status")] public long FollowStatus { get; set; }
|
||||
|
||||
[JsonProperty("short_id")] public string ShortId { get; set; }
|
||||
|
||||
[JsonProperty("following_count")] public long FollowingCount { get; set; }
|
||||
|
||||
[JsonProperty("nickname")] public string Nickname { get; set; }
|
||||
|
||||
[JsonProperty("favoriting_count")] public long FavoritingCount { get; set; }
|
||||
}
|
||||
|
||||
public class AvatarMedium
|
||||
{
|
||||
[JsonProperty("url_list")] public List<Uri> UrlList { get; set; }
|
||||
|
||||
[JsonProperty("uri")] public string Uri { get; set; }
|
||||
}
|
||||
|
||||
public class MixInfo
|
||||
{
|
||||
[JsonProperty("mix_id")] public string MixId { get; set; }
|
||||
|
||||
[JsonProperty("cover_url")] public AvatarMedium CoverUrl { get; set; }
|
||||
|
||||
[JsonProperty("next_info")] public NextInfo NextInfo { get; set; }
|
||||
|
||||
[JsonProperty("statis")] public Statis Statis { get; set; }
|
||||
|
||||
[JsonProperty("create_time")] public long CreateTime { get; set; }
|
||||
|
||||
[JsonProperty("extra")] public string Extra { get; set; }
|
||||
|
||||
[JsonProperty("mix_name")] public string MixName { get; set; }
|
||||
|
||||
[JsonProperty("status")] public Status Status { get; set; }
|
||||
|
||||
[JsonProperty("desc")] public string Desc { get; set; }
|
||||
}
|
||||
|
||||
public class NextInfo
|
||||
{
|
||||
[JsonProperty("cover_url")] public AvatarMedium CoverUrl { get; set; }
|
||||
|
||||
[JsonProperty("mix_name")] public string MixName { get; set; }
|
||||
|
||||
[JsonProperty("desc")] public string Desc { get; set; }
|
||||
}
|
||||
|
||||
public class Statis
|
||||
{
|
||||
[JsonProperty("collect_vv")] public long CollectVv { get; set; }
|
||||
|
||||
[JsonProperty("current_episode")] public long CurrentEpisode { get; set; }
|
||||
|
||||
[JsonProperty("play_vv")] public long PlayVv { get; set; }
|
||||
|
||||
[JsonProperty("updated_to_episode")] public long UpdatedToEpisode { get; set; }
|
||||
}
|
||||
|
||||
public class Status
|
||||
{
|
||||
[JsonProperty("is_collected")] public long IsCollected { get; set; }
|
||||
|
||||
[JsonProperty("status")] public long StatusStatus { get; set; }
|
||||
}
|
||||
|
||||
public class Music
|
||||
{
|
||||
[JsonProperty("duration")] public long Duration { get; set; }
|
||||
|
||||
[JsonProperty("author")] public string Author { get; set; }
|
||||
|
||||
[JsonProperty("cover_medium")] public AvatarMedium CoverMedium { get; set; }
|
||||
|
||||
[JsonProperty("mid")] public string Mid { get; set; }
|
||||
|
||||
[JsonProperty("title")] public string Title { get; set; }
|
||||
|
||||
[JsonProperty("cover_hd")] public AvatarMedium CoverHd { get; set; }
|
||||
|
||||
[JsonProperty("cover_large")] public AvatarMedium CoverLarge { get; set; }
|
||||
|
||||
[JsonProperty("cover_thumb")] public AvatarMedium CoverThumb { get; set; }
|
||||
|
||||
[JsonProperty("status")] public long Status { get; set; }
|
||||
}
|
||||
|
||||
public class RiskInfos
|
||||
{
|
||||
[JsonProperty("warn")] public bool Warn { get; set; }
|
||||
|
||||
[JsonProperty("type")] public long Type { get; set; }
|
||||
|
||||
[JsonProperty("content")] public string Content { get; set; }
|
||||
|
||||
[JsonProperty("reflow_unplayable")] public long ReflowUnplayable { get; set; }
|
||||
}
|
||||
|
||||
public class Statistics
|
||||
{
|
||||
[JsonProperty("comment_count")] public long CommentCount { get; set; }
|
||||
|
||||
[JsonProperty("share_count")] public long ShareCount { get; set; }
|
||||
|
||||
[JsonProperty("aweme_id")] public string AwemeId { get; set; }
|
||||
|
||||
[JsonProperty("digg_count")] public long DiggCount { get; set; }
|
||||
|
||||
[JsonProperty("play_count")] public long PlayCount { get; set; }
|
||||
|
||||
[JsonProperty("collect_count")] public long CollectCount { get; set; }
|
||||
}
|
||||
|
||||
public class TextExtra
|
||||
{
|
||||
[JsonProperty("hashtag_id")] public long HashtagId { get; set; }
|
||||
|
||||
[JsonProperty("start")] public long Start { get; set; }
|
||||
|
||||
[JsonProperty("end")] public long End { get; set; }
|
||||
|
||||
[JsonProperty("type")] public long Type { get; set; }
|
||||
|
||||
[JsonProperty("hashtag_name")] public string HashtagName { get; set; }
|
||||
}
|
||||
|
||||
public class Video
|
||||
{
|
||||
[JsonProperty("cover")] public AvatarMedium Cover { get; set; }
|
||||
|
||||
[JsonProperty("play_addr")] public AvatarMedium PlayAddr { get; set; }
|
||||
|
||||
[JsonProperty("width")] public long Width { get; set; }
|
||||
|
||||
[JsonProperty("height")] public long Height { get; set; }
|
||||
}
|
||||
177
VideoDownload/Platforms/DouYin.cs
Normal file
177
VideoDownload/Platforms/DouYin.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
using System.ComponentModel;
|
||||
using System.Text.RegularExpressions;
|
||||
using Downloader;
|
||||
using Newtonsoft.Json;
|
||||
using RestSharp;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
public class DouYin : DownloadPlatforms
|
||||
{
|
||||
private static readonly Dictionary<string, string> _defaultHeaders = new()
|
||||
{
|
||||
{
|
||||
"User-Agent",
|
||||
"Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36"
|
||||
},
|
||||
{ "sec-fetch-site", "same-origin" },
|
||||
{ "sec-fetch-mode", "cors" },
|
||||
{ "sec-fetch-dest", "empty" },
|
||||
{ "sec-ch-ua-platform", "Windows" },
|
||||
{ "sec-ch-ua-mobile", "?0" },
|
||||
{ "sec-ch-ua", "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"126\", \"Google Chrome\";v=\"126\"" },
|
||||
{ "referer", "https://www.douyin.com/?recommend=1" },
|
||||
{ "priority", "u=1, i" },
|
||||
{ "pragma", "no-cache" },
|
||||
{ "cache-control", "no-cache" },
|
||||
{ "accept-language", "zh-CN,zh;q=0.9,en;q=0.8" },
|
||||
{
|
||||
"accept",
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
|
||||
},
|
||||
{ "dnt", "1" }
|
||||
};
|
||||
|
||||
public async override Task<string> ExtractUrlAsync(string text)
|
||||
{
|
||||
Log.Info($"开始解析抖音链接 {text}");
|
||||
return Regex.Match(text, @"https?://[^\s]+").Value;
|
||||
}
|
||||
|
||||
public override async Task<VideoModel> ParseShare(string DownloadUrlText)
|
||||
{
|
||||
if (!DownloadUrlText.Contains("https://"))
|
||||
{
|
||||
Log.Error("请输入正确的分享链接");
|
||||
return null;
|
||||
}
|
||||
|
||||
var downloadUrl = await ExtractUrlAsync(DownloadUrlText);
|
||||
VideoModel Data = await ExtractVideoDataAsync(downloadUrl);
|
||||
Data.ShareId = downloadUrl.Replace("https://v.douyin.com/", "").Replace("/", "");
|
||||
|
||||
return Data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据链接 https://v.douyin.com/ircqoExo/ 解析出页面中的数据
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
public override Task<VideoModel> ExtractVideoDataAsync(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.Info($"开始解析链接 {url}");
|
||||
// 创建RestClient
|
||||
RestClient client = new(url);
|
||||
|
||||
// 创建请求对象
|
||||
RestRequest request = new();
|
||||
|
||||
// 设置 User-Agent 模拟手机浏览器
|
||||
request.AddHeaders(_defaultHeaders);
|
||||
|
||||
// 发送请求并获取响应
|
||||
var response = client.Execute(request);
|
||||
if (!response.IsSuccessful) throw new HttpRequestException("request is fail");
|
||||
|
||||
var content = response.Content;
|
||||
Log.Info($"开始解析响应内容 {content}");
|
||||
if (content is null) throw new InvalidDataException("content is null");
|
||||
|
||||
const string routerDataPattern = @"_ROUTER_DATA\s*=\s*(\{.*?\})<";
|
||||
|
||||
var matchJson = Regex.Match(content, routerDataPattern);
|
||||
|
||||
Log.Info($"开始解析匹配到的json {matchJson}");
|
||||
if (matchJson.Groups.Count < 2) throw new InvalidDataException("未匹配到合法的数据,matchJson.Groups.Count < 2");
|
||||
|
||||
var videoJson = matchJson.Groups[1].Value;
|
||||
Log.Info($"开始解析匹配到的json {videoJson}");
|
||||
// 反序列化JSON字符串为C#对象
|
||||
var videoData = JsonConvert.DeserializeObject<DouYinShareRouterData>(videoJson);
|
||||
|
||||
if (videoData is null) throw new InvalidDataException("JSON解析数据为空,请检查分享链接是否正确,如有更多问题请查看日志");
|
||||
|
||||
var videoInfoData = videoData.LoaderData.VideoIdPage.VideoInfoRes.ItemList.First();
|
||||
|
||||
var video = new VideoModel
|
||||
{
|
||||
Platform = ShortVideoPlatformEnum.DouYin,
|
||||
VideoId = videoInfoData.AwemeId,
|
||||
AuthorName = videoInfoData.Author.Nickname,
|
||||
UniqueId = videoInfoData.Author.UniqueId == ""
|
||||
? videoInfoData.Author.ShortId
|
||||
: videoInfoData.Author.UniqueId,
|
||||
AuthorAvatar = videoInfoData.Author.AvatarThumb.UrlList.First().ToString(),
|
||||
Title = videoInfoData.Author.Signature,
|
||||
Cover = videoInfoData.Video.Cover.UrlList.Last().ToString(),
|
||||
Mp3Url = "",
|
||||
CreatedTime =
|
||||
DateTimeOffset.FromUnixTimeSeconds(videoInfoData.CreateTime)
|
||||
.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
Desc = videoInfoData.Desc,
|
||||
Duration = "",
|
||||
DiggCount = videoInfoData.Statistics.DiggCount,
|
||||
CollectCount = videoInfoData.Statistics.CollectCount,
|
||||
CommentCount = videoInfoData.Statistics.CommentCount,
|
||||
ShareCount = videoInfoData.Statistics.ShareCount
|
||||
};
|
||||
switch (videoInfoData.AwemeType)
|
||||
{
|
||||
case 2:
|
||||
video.VideoUrl = videoInfoData.Video.Cover.UrlList.First().ToString();
|
||||
break;
|
||||
default:
|
||||
video.VideoUrl = videoInfoData.Video.PlayAddr.UrlList.First().ToString().Replace("playwm", "play");
|
||||
break;
|
||||
}
|
||||
|
||||
if (video.VideoUrl.Contains("ratio=720p"))
|
||||
{
|
||||
video.VideoUrl = video.VideoUrl.Replace("ratio=720p", "ratio=1080p");
|
||||
}
|
||||
|
||||
return Task.FromResult(video);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> DownloadAsync(string url, string savePath, string fileName,
|
||||
EventHandler<DownloadProgressChangedEventArgs> onProgressChanged,
|
||||
EventHandler<AsyncCompletedEventArgs> onProgressCompleted)
|
||||
{
|
||||
DownloadConfiguration downloadConfiguration = new()
|
||||
{
|
||||
ChunkCount = 8, // Download in 8 chunks (increase for larger files)
|
||||
MaxTryAgainOnFailure = 5,
|
||||
Timeout = 10000, // 10 seconds timeout for each request
|
||||
RequestConfiguration = new RequestConfiguration
|
||||
{
|
||||
UserAgent = _defaultHeaders.GetValueOrDefault("User-Agent")
|
||||
}
|
||||
};
|
||||
|
||||
DownloadService downloader = new(downloadConfiguration);
|
||||
|
||||
downloader.DownloadProgressChanged += onProgressChanged;
|
||||
downloader.DownloadFileCompleted += onProgressCompleted;
|
||||
|
||||
try
|
||||
{
|
||||
await downloader.DownloadFileTaskAsync(url, Path.Combine(savePath, fileName));
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Info($"Download failed: {ex}");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
15
VideoDownload/Platforms/DownloadPlatforms.cs
Normal file
15
VideoDownload/Platforms/DownloadPlatforms.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.ComponentModel;
|
||||
using Downloader;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
public abstract class DownloadPlatforms
|
||||
{
|
||||
public abstract Task<string> ExtractUrlAsync(string text);
|
||||
public abstract Task<VideoModel> ParseShare(string DownloadUrlText);
|
||||
public abstract Task<VideoModel> ExtractVideoDataAsync(string url);
|
||||
|
||||
public abstract Task<bool> DownloadAsync(string url, string savePath, string fileName,
|
||||
EventHandler<DownloadProgressChangedEventArgs> onProgressChanged,
|
||||
EventHandler<AsyncCompletedEventArgs> onProgressCompleted);
|
||||
}
|
||||
53
VideoDownload/Platforms/KuaiShou.cs
Normal file
53
VideoDownload/Platforms/KuaiShou.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System.ComponentModel;
|
||||
using Downloader;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
public class KuaiShou : DownloadPlatforms
|
||||
{
|
||||
private static readonly Dictionary<string, string> _defaultHeaders = new()
|
||||
{
|
||||
{
|
||||
"User-Agent",
|
||||
"Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36"
|
||||
},
|
||||
{ "sec-fetch-site", "same-origin" },
|
||||
{ "sec-fetch-mode", "cors" },
|
||||
{ "sec-fetch-dest", "empty" },
|
||||
{ "sec-ch-ua-platform", "Windows" },
|
||||
{ "sec-ch-ua-mobile", "?0" },
|
||||
{ "sec-ch-ua", "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"126\", \"Google Chrome\";v=\"126\"" },
|
||||
{ "referer", "https://www.douyin.com/?recommend=1" },
|
||||
{ "priority", "u=1, i" },
|
||||
{ "pragma", "no-cache" },
|
||||
{ "cache-control", "no-cache" },
|
||||
{ "accept-language", "zh-CN,zh;q=0.9,en;q=0.8" },
|
||||
{
|
||||
"accept",
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
|
||||
},
|
||||
{ "dnt", "1" }
|
||||
};
|
||||
|
||||
public override Task<string> ExtractUrlAsync(string text)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<VideoModel> ParseShare(string DownloadUrlText)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<VideoModel> ExtractVideoDataAsync(string url)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<bool> DownloadAsync(string url, string savePath, string fileName,
|
||||
EventHandler<DownloadProgressChangedEventArgs> onProgressChanged,
|
||||
EventHandler<AsyncCompletedEventArgs> onProgressCompleted)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
151
VideoDownload/VideoDownload.cs
Normal file
151
VideoDownload/VideoDownload.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using System.Threading.Channels;
|
||||
|
||||
namespace ACBuildService;
|
||||
|
||||
public static class VideoDownload
|
||||
{
|
||||
private static readonly Channel<string> _queue = Channel.CreateUnbounded<string>();
|
||||
private static readonly CancellationTokenSource _cts = new CancellationTokenSource();
|
||||
private static readonly TimeSpan _interval = TimeSpan.FromSeconds(20);
|
||||
|
||||
|
||||
static VideoDownload()
|
||||
{
|
||||
Task.Run(ProcessQueueAsync);
|
||||
}
|
||||
|
||||
public static void Add(string shareText)
|
||||
{
|
||||
_queue.Writer.TryWrite(shareText);
|
||||
}
|
||||
|
||||
private static async Task ProcessQueueAsync()
|
||||
{
|
||||
var timer = new PeriodicTimer(_interval);
|
||||
|
||||
try
|
||||
{
|
||||
while (await _queue.Reader.WaitToReadAsync(_cts.Token) &&
|
||||
await timer.WaitForNextTickAsync(_cts.Token))
|
||||
{
|
||||
if (_queue.Reader.TryRead(out var shareText))
|
||||
{
|
||||
// 这里开始处理任务,这个处理过程本身的时间不计入间隔
|
||||
// PeriodicTimer 会保证两次 WaitForNextTickAsync 之间间隔10秒
|
||||
await ProcessVideoDownloadAsync(shareText);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 正常取消
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task ProcessVideoDownloadAsync(string shareText)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = GetService(shareText);
|
||||
if (service != null)
|
||||
{
|
||||
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 开始处理: {shareText}");
|
||||
await DownloadVideoAsync(service, shareText);
|
||||
|
||||
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 处理完成: {shareText}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] 处理失败: {shareText}, 错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// 模拟下载视频的方法
|
||||
private static async Task DownloadVideoAsync(DownloadPlatforms service, string shareText)
|
||||
{
|
||||
//开始解析数据
|
||||
var videoModel = await service.ParseShare(shareText);
|
||||
if (videoModel == null) return;
|
||||
|
||||
var rootPath = $"{HttpService.BaseRootPath}videos/";
|
||||
var t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
var fileName = $"{t}.mp4";
|
||||
var filePath = Path.Combine(rootPath, fileName);
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
Log.Error("文件已存在");
|
||||
return;
|
||||
}
|
||||
|
||||
var ret = await service.DownloadAsync(videoModel.VideoUrl, rootPath, fileName, null, null);
|
||||
if (ret)
|
||||
{
|
||||
var dbItem = new VideoTable
|
||||
{
|
||||
SourcePath = shareText,
|
||||
FilePath = fileName,
|
||||
AuthorName = videoModel.AuthorName,
|
||||
Title = videoModel.Title,
|
||||
Desc = videoModel.Desc,
|
||||
Duration = videoModel.Duration,
|
||||
Like = (int)videoModel.DiggCount,
|
||||
Collect = (int)videoModel.CollectCount,
|
||||
Message = (int)videoModel.CommentCount,
|
||||
Share = (int)videoModel.ShareCount,
|
||||
CreateTime = DateTime.Now
|
||||
};
|
||||
DB.Main.Insertable(dbItem).ExecuteCommand();
|
||||
}
|
||||
|
||||
//解析数据后等待一会
|
||||
await Task.Delay(3000);
|
||||
}
|
||||
|
||||
#region Service
|
||||
|
||||
private static Dictionary<ShortVideoPlatformEnum, DownloadPlatforms> _services =
|
||||
new Dictionary<ShortVideoPlatformEnum, DownloadPlatforms>();
|
||||
|
||||
private static DownloadPlatforms GetService(string text)
|
||||
{
|
||||
var platform = GetPlatform(text);
|
||||
if (_services.TryGetValue(platform, out var value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
if (platform == ShortVideoPlatformEnum.DouYin)
|
||||
{
|
||||
value = new DouYin();
|
||||
}
|
||||
else if (platform == ShortVideoPlatformEnum.KuaiShou)
|
||||
{
|
||||
value = new KuaiShou();
|
||||
}
|
||||
|
||||
if (value != null)
|
||||
{
|
||||
_services[platform] = value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static ShortVideoPlatformEnum GetPlatform(string text)
|
||||
{
|
||||
if (text.Contains("douyin"))
|
||||
{
|
||||
return ShortVideoPlatformEnum.DouYin;
|
||||
}
|
||||
|
||||
if (text.Contains("kuaishou"))
|
||||
{
|
||||
return ShortVideoPlatformEnum.KuaiShou;
|
||||
}
|
||||
|
||||
return ShortVideoPlatformEnum.None;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
200
VideoDownload/VideoDownloadService.cs
Normal file
200
VideoDownload/VideoDownloadService.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
// using System.ComponentModel;
|
||||
// using System.Text.RegularExpressions;
|
||||
// using Downloader;
|
||||
// using Newtonsoft.Json;
|
||||
// using RestSharp;
|
||||
//
|
||||
// namespace ACBuildService;
|
||||
//
|
||||
// public class VideoDownloadService
|
||||
// {
|
||||
// private static readonly Dictionary<string, string> _defaultHeaders = new()
|
||||
// {
|
||||
// {
|
||||
// "User-Agent",
|
||||
// "Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36"
|
||||
// },
|
||||
// { "sec-fetch-site", "same-origin" },
|
||||
// { "sec-fetch-mode", "cors" },
|
||||
// { "sec-fetch-dest", "empty" },
|
||||
// { "sec-ch-ua-platform", "Windows" },
|
||||
// { "sec-ch-ua-mobile", "?0" },
|
||||
// { "sec-ch-ua", "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"126\", \"Google Chrome\";v=\"126\"" },
|
||||
// { "referer", "https://www.douyin.com/?recommend=1" },
|
||||
// { "priority", "u=1, i" },
|
||||
// { "pragma", "no-cache" },
|
||||
// { "cache-control", "no-cache" },
|
||||
// { "accept-language", "zh-CN,zh;q=0.9,en;q=0.8" },
|
||||
// {
|
||||
// "accept",
|
||||
// "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
|
||||
// },
|
||||
// { "dnt", "1" }
|
||||
// };
|
||||
//
|
||||
// public async Task<VideoModel> ParseShare(string DownloadUrlText)
|
||||
// {
|
||||
// if (!DownloadUrlText.Contains("https://"))
|
||||
// {
|
||||
// // throw new ValidationException("请输入正确的分享链接");
|
||||
// Log.Error("请输入正确的分享链接");
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// VideoModel Data = null;
|
||||
//
|
||||
// if (DownloadUrlText.Contains(ShortVideoPlatformEnum.DouYin.ToString().ToLower()))
|
||||
// {
|
||||
// var downloadUrl = await ExtractUrlAsync(DownloadUrlText);
|
||||
// Data = await ExtractVideoDataAsync(downloadUrl);
|
||||
// Data.ShareId = downloadUrl.Replace("https://v.douyin.com/", "").Replace("/", "");
|
||||
// }
|
||||
//
|
||||
// // else if (DownloadUrlText.Contains(ShortVideoPlatformEnum.KuaiShou.ToString().ToLower()))
|
||||
// // {
|
||||
// // var downloadUrl = await _kuaiShortVideoService.ExtractUrlAsync(DownloadUrlText);
|
||||
// // Data = await _kuaiShortVideoService.ExtractVideoDataAsync(downloadUrl);
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // throw new ValidationException("暂不支持该平台");
|
||||
// // }
|
||||
// // Log.Info($"解析结果 data={JSON.Serialize(Data)}");
|
||||
// return Data;
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 解析dy分享中的文本 6.17 05/18 U@L.wf fbn:/ 悬疑推理:亡者和自己的手机上午一同下葬,下午却给警察发来短信 本期的故事,来自于高分推理神剧《天堂岛疑云》中的谜案《亡灵的短信》。# 悬疑推理 # 每日推荐电影
|
||||
// /// # 一剪到底 https://v.douyin.com/ircqoExo/ 复制此链接,打开Dou音搜索,直接观看视频!
|
||||
// /// https://v.douyin.com/ircqoExo/
|
||||
// /// </summary>
|
||||
// /// <param name="text"></param>
|
||||
// /// <returns></returns>
|
||||
// public async Task<string> ExtractUrlAsync(string text)
|
||||
// {
|
||||
// Log.Info($"开始解析抖音链接 {text}");
|
||||
// return Regex.Match(text, @"https?://[^\s]+").Value;
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 根据链接 https://v.douyin.com/ircqoExo/ 解析出页面中的数据
|
||||
// /// </summary>
|
||||
// /// <param name="url"></param>
|
||||
// /// <returns></returns>
|
||||
// public Task<VideoModel> ExtractVideoDataAsync(string url)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// Log.Info($"开始解析链接 {url}");
|
||||
// // 创建RestClient
|
||||
// RestClient client = new(url);
|
||||
//
|
||||
// // 创建请求对象
|
||||
// RestRequest request = new();
|
||||
//
|
||||
// // 设置 User-Agent 模拟手机浏览器
|
||||
// request.AddHeaders(_defaultHeaders);
|
||||
//
|
||||
// // 发送请求并获取响应
|
||||
// var response = client.Execute(request);
|
||||
// if (!response.IsSuccessful) throw new HttpRequestException("request is fail");
|
||||
//
|
||||
// var content = response.Content;
|
||||
// Log.Info($"开始解析响应内容 {content}");
|
||||
// if (content is null) throw new InvalidDataException("content is null");
|
||||
//
|
||||
// const string routerDataPattern = @"_ROUTER_DATA\s*=\s*(\{.*?\})<";
|
||||
//
|
||||
// var matchJson = Regex.Match(content, routerDataPattern);
|
||||
//
|
||||
// Log.Info($"开始解析匹配到的json {matchJson}");
|
||||
// if (matchJson.Groups.Count < 2) throw new InvalidDataException("未匹配到合法的数据,matchJson.Groups.Count < 2");
|
||||
//
|
||||
// var videoJson = matchJson.Groups[1].Value;
|
||||
// Log.Info($"开始解析匹配到的json {videoJson}");
|
||||
// // 反序列化JSON字符串为C#对象
|
||||
// var videoData = JsonConvert.DeserializeObject<DouYinShareRouterData>(videoJson);
|
||||
//
|
||||
// if (videoData is null) throw new InvalidDataException("JSON解析数据为空,请检查分享链接是否正确,如有更多问题请查看日志");
|
||||
//
|
||||
// var videoInfoData = videoData.LoaderData.VideoIdPage.VideoInfoRes.ItemList.First();
|
||||
//
|
||||
// var video = new VideoModel
|
||||
// {
|
||||
// Platform = ShortVideoPlatformEnum.DouYin,
|
||||
// VideoId = videoInfoData.AwemeId,
|
||||
// AuthorName = videoInfoData.Author.Nickname,
|
||||
// UniqueId = videoInfoData.Author.UniqueId == ""
|
||||
// ? videoInfoData.Author.ShortId
|
||||
// : videoInfoData.Author.UniqueId,
|
||||
// AuthorAvatar = videoInfoData.Author.AvatarThumb.UrlList.First().ToString(),
|
||||
// Title = videoInfoData.Author.Signature,
|
||||
// Cover = videoInfoData.Video.Cover.UrlList.Last().ToString(),
|
||||
// Mp3Url = "",
|
||||
// CreatedTime =
|
||||
// DateTimeOffset.FromUnixTimeSeconds(videoInfoData.CreateTime)
|
||||
// .ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
// Desc = videoInfoData.Desc,
|
||||
// Duration = "",
|
||||
// DiggCount = videoInfoData.Statistics.DiggCount,
|
||||
// CollectCount = videoInfoData.Statistics.CollectCount,
|
||||
// CommentCount = videoInfoData.Statistics.CommentCount,
|
||||
// ShareCount = videoInfoData.Statistics.ShareCount
|
||||
// };
|
||||
// switch (videoInfoData.AwemeType)
|
||||
// {
|
||||
// case 2:
|
||||
// video.VideoUrl = videoInfoData.Video.Cover.UrlList.First().ToString();
|
||||
// break;
|
||||
// default:
|
||||
// video.VideoUrl = videoInfoData.Video.PlayAddr.UrlList.First().ToString().Replace("playwm", "play");
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// if (video.VideoUrl.Contains("ratio=720p"))
|
||||
// {
|
||||
// video.VideoUrl = video.VideoUrl.Replace("ratio=720p", "ratio=1080p");
|
||||
// }
|
||||
//
|
||||
// return Task.FromResult(video);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// Log.Error(e.Message);
|
||||
// throw;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public async Task DownloadAsync(string url, string savePath, string fileName,
|
||||
// EventHandler<DownloadProgressChangedEventArgs> onProgressChanged,
|
||||
// EventHandler<AsyncCompletedEventArgs> onProgressCompleted
|
||||
// )
|
||||
// {
|
||||
// DownloadConfiguration downloadConfiguration = new()
|
||||
// {
|
||||
// ChunkCount = 8, // Download in 8 chunks (increase for larger files)
|
||||
// MaxTryAgainOnFailure = 5,
|
||||
// Timeout = 10000, // 10 seconds timeout for each request
|
||||
// RequestConfiguration = new RequestConfiguration
|
||||
// {
|
||||
// UserAgent = _defaultHeaders.GetValueOrDefault("User-Agent")
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// DownloadService downloader = new(downloadConfiguration);
|
||||
//
|
||||
// downloader.DownloadProgressChanged += onProgressChanged;
|
||||
// downloader.DownloadFileCompleted += onProgressCompleted;
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// await downloader.DownloadFileTaskAsync(url, savePath + fileName);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Log.Info($"Download failed: {ex}");
|
||||
// throw;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
70
VideoDownload/VideoModel.cs
Normal file
70
VideoDownload/VideoModel.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
namespace ACBuildService;
|
||||
|
||||
public enum ShortVideoPlatformEnum
|
||||
{
|
||||
None,
|
||||
// 抖音
|
||||
DouYin,
|
||||
|
||||
// 快手
|
||||
KuaiShou,
|
||||
|
||||
/// <summary>
|
||||
/// B站
|
||||
/// </summary>
|
||||
Bilibili,
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class VideoModel
|
||||
{
|
||||
// 短视频所属的平台
|
||||
public ShortVideoPlatformEnum Platform { get; set; }
|
||||
|
||||
// 视频ID
|
||||
public string VideoId { get; set; }
|
||||
|
||||
// 作者
|
||||
public string AuthorName { get; set; }
|
||||
|
||||
// Unique Id
|
||||
public string UniqueId { get; set; }
|
||||
|
||||
// 头像
|
||||
public string AuthorAvatar { get; set; }
|
||||
|
||||
// 视频标题
|
||||
public string Title { get; set; }
|
||||
|
||||
// 封面
|
||||
public string Cover { get; set; }
|
||||
|
||||
// 收藏数
|
||||
public long CollectCount { get; set; }
|
||||
|
||||
// 点赞数
|
||||
public long DiggCount { get; set; }
|
||||
|
||||
// 分享数
|
||||
public long ShareCount { get; set; }
|
||||
|
||||
// 评论数
|
||||
public long CommentCount { get; set; }
|
||||
|
||||
// 视频地址
|
||||
public string VideoUrl { get; set; }
|
||||
|
||||
// 音频地址
|
||||
public string Mp3Url { get; set; }
|
||||
|
||||
// 创建时间
|
||||
public string CreatedTime { get; set; }
|
||||
|
||||
// 视频描述
|
||||
public string Desc { get; set; }
|
||||
|
||||
// 视频时长
|
||||
public string Duration { get; set; }
|
||||
|
||||
public string ShareId { get; set; }
|
||||
}
|
||||
7
appsettings.json
Normal file
7
appsettings.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"Debug": true,
|
||||
"HttpPort": 9888,
|
||||
"OpenProxy": true,
|
||||
"ProxyHost": "http://127.0.0.1:10808",
|
||||
"Password": "123456"
|
||||
}
|
||||
7
global.json
Normal file
7
global.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "8.0.0",
|
||||
"rollForward": "latestMajor",
|
||||
"allowPrerelease": true
|
||||
}
|
||||
}
|
||||
13
project-game-x-f720ef30f678.json
Normal file
13
project-game-x-f720ef30f678.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"type": "service_account",
|
||||
"project_id": "project-game-x",
|
||||
"private_key_id": "f720ef30f678d5c76f101b3eebdcb578460b27e2",
|
||||
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCtT0hy5GxzK+LI\nl0si8K7e8UrKDj+39YEti2hTrnA5NLed+zKOBMKl7vTJLCweE3RMPamkpYPtbwXc\neERB7s5+Bg4Bqq4uCkNov3uHBt19nyGPFhK3i6nIcm8tk+v8LLEMCnXy5R2hwU9J\naRtJoymP2fPbDeOEuSl8eeQw7kla2CXASrmNS8sTSnX3GAjqKIGmByRHQSa+Hn4R\nxVsqtL1sck9XAgITZQ9ciiWJAfX0caciU9merZHmTXI8lpJgE+7IjLi5RTlVQYg9\nkjY3CjZJAlDvFp/BN0laNzhSu8Z0bO/J1JrpGDn/jc+k0VZKK0JIDMUorvimFneh\n9kJwN5W7AgMBAAECggEAEsOhF3dt2oZni8pTA0RwhTOLd8GqhR4FT3YRj0XgDAGO\nLoJSYJgEBHfmdEWJEp85RJaZ4HlfMFIzSJc+OgPuGCz1pUPij0TjNDB54mO25XFY\n7ny4UrvCCobWohEASDxagEWTAapsK+WZ0lvumBQcsuDT4JAUuyZaZzTB+nOXk53i\nG0bj2CTCm3IJK0u/6gSuPIiMDjrMGOhYlATCeEY3kL6MJBiU96UGacuwBxXwHVO1\ntSH9vac7Nen1V9PSDZAhQQIldt6gFEjj5trKt4QMty0prbQCJvec4dXEVtO6HaLe\n1ZaUC2hyqWyL3kd14T/dlo6ZBCx3kp8j+UiBFQ6r4QKBgQDv9VXds+lKyH8V50xh\nrPLElg2ovpQ0d7LjBwopznNWIGSD0LFB+ihVI3itf5CXS3vIGztvEooRB6BVFW15\na9P5gfVmwVO/xZ5kZz/d0W8Hk6WoE2JFbNSGDj4eHRYSdbvzSZnwPfx1A+bmuXeL\nCA33dlMInl7k7P1w6EbPwRGpawKBgQC45VFfEJ97iNBhRsIAMVGU8pQX2G0TbgGg\nP4OBnARprf2Tb4ky3iENoWpM2OUHng8f80yaIrTqhqzNz/cb9XU3Y+6yatyTRrMw\nKUC369mjRPt1LL9vIr0JTwdANve/Uom3UneINsxSiPm2Dh5Rr0XNVeLI9aDjwnn4\nrPHIbBNI8QKBgHlSMlLAdtBfpJl/c0fjOG8aateJW8dXSbOtSH8wqXG/OPLIXga8\now3AvHAEEifcez4GPrt+xR2tHGxIRCxizy7UfS2xy1UnZljfNxRAooFTLitXeZUe\nXClXJCL3k8RLkHaGHPWxcWX8Tg8TcJRzwxP92CeAYvwdsloWpk6+D973AoGAJPD8\nTwgdNStipuziOfOgnyfQWutM78Lc5E2MUsr/PrYaoeh4+wbSh8ymVnBHYjw8PV/5\nABrLFsiNohlY/+cM4mI/ALrFE0/e4VJ8scKXmz1fGEw2e1fvePqnMjdJTJqLFWuO\nolKAhEUFz1AG0r84LQxp4UjiOl9Sy1KShD7Do6ECgYAkWZ6vXsvxNAfD2BnbPJ2j\nAB5r0RgN6PfPF4c/aJ8NOc/Dfi+myaKs5JEdtDIibO1+W6dfPWmaMMD/TkU5KgUU\nk4oGLEyWKD++dyt0y3PiKfoGsA9Xhhn9SK8pkqVphwfA1NSRrof5Jpo4OMZeB/ZF\nmRU+h5VqRGxR5eeSvOJinQ==\n-----END PRIVATE KEY-----\n",
|
||||
"client_email": "ac-auto-update@project-game-x.iam.gserviceaccount.com",
|
||||
"client_id": "108075195906651298317",
|
||||
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||
"token_uri": "https://oauth2.googleapis.com/token",
|
||||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
||||
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/ac-auto-update%40project-game-x.iam.gserviceaccount.com",
|
||||
"universe_domain": "googleapis.com"
|
||||
}
|
||||
43
wwwroot/home.html
Normal file
43
wwwroot/home.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>导航页</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
}
|
||||
.container {
|
||||
text-align: center;
|
||||
}
|
||||
.button {
|
||||
display: inline-block;
|
||||
margin: 10px;
|
||||
padding: 15px 25px;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
background-color: #007BFF;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
.button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<a href="/files" class="button">文件列表</a>
|
||||
<a href="/page/log" class="button">日志列表</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user