├── N_m3u8DL-CLI-SimpleG
├── Properties
│ ├── Resources.en-US.Designer.cs
│ ├── Resources.zh-TW.Designer.cs
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.resx
│ ├── Resources.zh-TW.resx
│ ├── Resources.en-US.resx
│ └── Resources.Designer.cs
├── logo_3Iv_icon.ico
├── packages.config
├── App.config
├── App.xaml
├── App.xaml.cs
├── N_m3u8DL-CLI-SimpleG.csproj
├── MainWindow.xaml
└── MainWindow.xaml.cs
├── README.md
├── LICENSE
├── N_m3u8DL-CLI-SimpleG.sln
├── .gitattributes
└── .gitignore
/N_m3u8DL-CLI-SimpleG/Properties/Resources.en-US.Designer.cs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/Properties/Resources.zh-TW.Designer.cs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/logo_3Iv_icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nilaoda/N_m3u8DL-CLI-SimpleG/HEAD/N_m3u8DL-CLI-SimpleG/logo_3Iv_icon.ico
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # N_m3u8DL-CLI-SimpleG
2 | N_m3u8DL-CLI's simple GUI
3 |
4 | ---
5 |
6 | 对应命令行工具:https://github.com/nilaoda/N_m3u8DL-CLI
7 |
8 | 相关说明:https://nilaoda.github.io/N_m3u8DL-CLI/SimpleGUI.html
9 |
10 | 没什么精力维护,开源
11 |
12 | 
13 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Globalization;
6 | using System.Linq;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using System.Windows;
10 |
11 | namespace N_m3u8DL_CLI_SimpleG
12 | {
13 | ///
14 | /// App.xaml 的交互逻辑
15 | ///
16 | public partial class App : Application
17 | {
18 | protected override void OnStartup(StartupEventArgs e)
19 | {
20 | string loc = "en-US";
21 | string currLoc = Thread.CurrentThread.CurrentUICulture.Name;
22 | if (currLoc == "zh-TW" || currLoc == "zh-HK" || currLoc == "zh-MO") loc = "zh-TW";
23 | else if (currLoc == "zh-CN" || currLoc == "zh-SG") loc = "zh-CN";
24 | //设置语言
25 | Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(loc);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace N_m3u8DL_CLI_SimpleG.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 nilaoda
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29009.5
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "N_m3u8DL-CLI-SimpleG", "N_m3u8DL-CLI-SimpleG\N_m3u8DL-CLI-SimpleG.csproj", "{527FA325-6ECD-40FB-A108-8C2747AE6BCD}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {527FA325-6ECD-40FB-A108-8C2747AE6BCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {527FA325-6ECD-40FB-A108-8C2747AE6BCD}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {527FA325-6ECD-40FB-A108-8C2747AE6BCD}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {527FA325-6ECD-40FB-A108-8C2747AE6BCD}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {2AE62102-3D14-448F-8C53-811AF11AB5D3}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // 有关程序集的一般信息由以下
8 | // 控制。更改这些特性值可修改
9 | // 与程序集关联的信息。
10 | [assembly: AssemblyTitle("N_m3u8DL-CLI-SimpleG")]
11 | [assembly: AssemblyDescription("N_m3u8DL-CLI的简易GUI程序")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("nilaoda")]
14 | [assembly: AssemblyProduct("N_m3u8DL-CLI-SimpleG")]
15 | [assembly: AssemblyCopyright("Copyright © 2022")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // 将 ComVisible 设置为 false 会使此程序集中的类型
20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
21 | //请将此类型的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible(false)]
23 |
24 | //若要开始生成可本地化的应用程序,请设置
25 | //.csproj 文件中的 CultureYouAreCodingWith
26 | //例如,如果您在源文件中使用的是美国英语,
27 | //使用的是美国英语,请将 设置为 en-US。 然后取消
28 | //对以下 NeutralResourceLanguage 特性的注释。 更新
29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置
36 | //(未在页面中找到资源时使用,
37 | //或应用程序资源字典中找到时使用)
38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
39 | //(未在页面中找到资源时使用,
40 | //、应用程序或任何主题专用资源字典中找到时使用)
41 | )]
42 |
43 |
44 | // 程序集的版本信息由下列四个值组成:
45 | //
46 | // 主版本
47 | // 次版本
48 | // 生成号
49 | // 修订号
50 | //
51 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
52 | //通过使用 "*",如下所示:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/N_m3u8DL-CLI-SimpleG.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Debug
7 | AnyCPU
8 | {527FA325-6ECD-40FB-A108-8C2747AE6BCD}
9 | WinExe
10 | N_m3u8DL_CLI_SimpleG
11 | N_m3u8DL-CLI-SimpleG
12 | v4.6
13 | 512
14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
15 | 4
16 | true
17 | true
18 |
19 |
20 | false
21 | publish\
22 | true
23 | Disk
24 | false
25 | Foreground
26 | 7
27 | Days
28 | false
29 | false
30 | true
31 | 0
32 | 1.0.0.%2a
33 | false
34 | true
35 | true
36 |
37 |
38 |
39 |
40 | AnyCPU
41 | true
42 | full
43 | false
44 | bin\Debug\
45 | DEBUG;TRACE
46 | prompt
47 | 4
48 | false
49 |
50 |
51 | AnyCPU
52 | pdbonly
53 | true
54 | bin\Release\
55 | TRACE
56 | prompt
57 | 4
58 | false
59 |
60 |
61 | logo_3Iv_icon.ico
62 |
63 |
64 |
65 | true
66 |
67 |
68 | E5E1164B3AE3A1D2A8D7B48ACB87479F6DB77431
69 |
70 |
71 | N_m3u8DL-CLI-SimpleG_TemporaryKey.pfx
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | 4.0
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | MSBuild:Compile
99 | Designer
100 |
101 |
102 | MSBuild:Compile
103 | Designer
104 |
105 |
106 | App.xaml
107 | Code
108 |
109 |
110 | MainWindow.xaml
111 | Code
112 |
113 |
114 |
115 |
116 | Code
117 |
118 |
119 | True
120 | True
121 | Resources.resx
122 |
123 |
124 | True
125 | True
126 | Resources.en-US.resx
127 |
128 |
129 | True
130 | True
131 | Resources.zh-TW.resx
132 |
133 |
134 | True
135 | Settings.settings
136 | True
137 |
138 |
139 | PublicResXFileCodeGenerator
140 | Resources.en-US.Designer.cs
141 |
142 |
143 | PublicResXFileCodeGenerator
144 | Resources.Designer.cs
145 |
146 |
147 | PublicResXFileCodeGenerator
148 | Resources.zh-TW.Designer.cs
149 |
150 |
151 |
152 |
153 | SettingsSingleFileGenerator
154 | Settings.Designer.cs
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 | False
166 | .NET Framework 3.5 SP1
167 | false
168 |
169 |
170 |
171 |
172 |
173 | 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。
174 |
175 |
176 |
177 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 仅合并音频轨道
122 |
123 |
124 | 下载全部分片,合并为音轨
125 |
126 |
127 | 设置m3u8文件的Baseurl
128 |
129 |
130 | 使用二进制合并
131 |
132 |
133 | 采用二进制直接追加合并文件
134 |
135 |
136 | 选择
137 |
138 |
139 | 选择存储目录
140 |
141 |
142 | 复制(_C)
143 |
144 |
145 | 剪切(_T)
146 |
147 |
148 | 合并后删除分片
149 |
150 |
151 | 勾选此项后合并完毕将删除所有分片
152 |
153 |
154 | 关闭完整性检查
155 |
156 |
157 | 下载完毕后跳过检查分片数量是否与m3u8内描述的文件数量一致
158 |
159 |
160 | 合并时不写入日期
161 |
162 |
163 | 使用ffmpeg混流时不写入Date属性
164 |
165 |
166 | 下载完成后不合并
167 |
168 |
169 | 不合并视频分片
170 |
171 |
172 | 不使用系统代理
173 |
174 |
175 | 不主动使用系统代理
176 |
177 |
178 | 执行程序
179 |
180 |
181 | 下载器主程序的文件名
182 |
183 |
184 | 混流MP4边下边看
185 |
186 |
187 | 使用ffmpeg混流时将元数据移动到头部
188 |
189 |
190 | 获取下载器(_N)
191 |
192 |
193 | 点击我即可调用下载器
194 |
195 |
196 | 请求头
197 |
198 |
199 | 为请求添加 HTTP Header
200 |
201 |
202 | 自定义IV
203 |
204 |
205 | 输入HEX字符串
206 |
207 |
208 | 自定义KEY
209 |
210 |
211 | 可拖入16字节的本地KEY文件或输入Base64字符串
212 |
213 |
214 | M3U8地址
215 |
216 |
217 | 可以输入或拖入文件; 拖入文件夹或txt以批量下载; 双击从剪贴板获取
218 |
219 |
220 | 限速(kb/s)
221 |
222 |
223 | 设置下载限速;0为不限制
224 |
225 |
226 | 最大线程
227 |
228 |
229 | 程序将尝试使用不高于此数值的线程下载
230 |
231 |
232 | 最小线程
233 |
234 |
235 | 程序将尝试使用不低于此数值的线程下载
236 |
237 |
238 | 混流文件
239 |
240 |
241 | 可拖入特定的json文件
242 |
243 |
244 | 启动参数
245 |
246 |
247 | 本程序生成的启动参数
248 |
249 |
250 | 仅解析m3u8
251 |
252 |
253 | 在解析m3u8之后退出程序,仅生成meta.json
254 |
255 |
256 | 粘贴(_P)
257 |
258 |
259 | 范围选择
260 |
261 |
262 | 设置开始时间或开始分片序号
263 |
264 |
265 | 设置终止时间或终止分片序号
266 |
267 |
268 | 重试次数
269 |
270 |
271 | 遇到停止速度时,程序尝试重新下载的次数
272 |
273 |
274 | 停速(kb/s)
275 |
276 |
277 | 当下载速度连续几次低于此数值时,重新下载
278 |
279 |
280 | 选择一个目录,视频将会下载到此处
281 |
282 |
283 | 找不到程序
284 |
285 |
286 | URL为必填项
287 |
288 |
289 | 请稍候
290 |
291 |
292 | 非预期的byte格式
293 |
294 |
295 | 非16 Bytes文件
296 |
297 |
298 | 超时时长(s)
299 |
300 |
301 | 设置请求超时时长
302 |
303 |
304 | 视频标题
305 |
306 |
307 | 双击此处可以自动获取视频标题
308 |
309 |
310 | 置顶窗口
311 |
312 |
313 | 置顶当前窗口
314 |
315 |
316 | 工作目录
317 |
318 |
319 | 存储目录,文件将会被下载到这里
320 |
321 |
322 | 设置代理
323 |
324 |
325 | 输入http/socks5代理地址,如http://127.0.0.1:8080.
326 |
327 |
328 | 不支持该代理链接!
329 |
330 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/Properties/Resources.zh-TW.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 最小線程
122 |
123 |
124 | 最大線程
125 |
126 |
127 | 自設KEY
128 |
129 |
130 | 自設IV
131 |
132 |
133 | 重試次數
134 |
135 |
136 | 置頂當前窗口
137 |
138 |
139 | 置頂窗口
140 |
141 |
142 | 執行程式
143 |
144 |
145 | 粘貼(_P)
146 |
147 |
148 | 在解析m3u8之後退出程式,僅生成meta.json
149 |
150 |
151 | 遇到停止速度時,程式嘗試重新下載的次數
152 |
153 |
154 | 選擇存儲目錄
155 |
156 |
157 | 選擇
158 |
159 |
160 | 限速(kb/s)
161 |
162 |
163 | 下載完成後不合並
164 |
165 |
166 | 下載完畢後跳過檢查分片數量是否與m3u8內描述的文件數量壹致
167 |
168 |
169 | 下載全部分片,合並為音軌
170 |
171 |
172 | 下載器主程式的文件名
173 |
174 |
175 | 為請求添加 HTTP Header
176 |
177 |
178 | 停速(kb/s)
179 |
180 |
181 | 雙擊此處可以自動獲取視頻標題
182 |
183 |
184 | 輸入HEX字符串
185 |
186 |
187 | 檔案標題
188 |
189 |
190 | 使用二進制合並
191 |
192 |
193 | 使用ffmpeg混流時將元數據移動到頭部
194 |
195 |
196 | 使用ffmpeg混流時不寫入Date屬性
197 |
198 |
199 | 設置終止時間或終止分片序號
200 |
201 |
202 | 設置下載限速;0為不限制
203 |
204 |
205 | 設置請求超時時長
206 |
207 |
208 | 設置開始時間或開始分片序號
209 |
210 |
211 | 設置m3u8文件的Baseurl
212 |
213 |
214 | 請求頭
215 |
216 |
217 | 啟動參數
218 |
219 |
220 | 可以輸入或拖入文件; 拖入文件夾或txt以批量下載; 雙擊從剪貼板獲取
221 |
222 |
223 | 可拖入特定的json文件
224 |
225 |
226 | 可拖入16字節的本地KEY文件或輸入Base64字符串
227 |
228 |
229 | 僅解析m3u8
230 |
231 |
232 | 僅合並音頻軌道
233 |
234 |
235 | 剪切(_T)
236 |
237 |
238 | 獲取下載器(_N)
239 |
240 |
241 | 混流文件
242 |
243 |
244 | 混流MP4邊下邊看
245 |
246 |
247 | 合並時不寫入日期
248 |
249 |
250 | 合並後刪除分片
251 |
252 |
253 | 關閉完整性檢查
254 |
255 |
256 | 勾選此項後合並完畢將刪除所有分片
257 |
258 |
259 | 工作目錄
260 |
261 |
262 | 復制(_C)
263 |
264 |
265 | 範圍選擇
266 |
267 |
268 | 點擊我即可調用下載器
269 |
270 |
271 | 當下載速度連續幾次低於此數值時,重新下載
272 |
273 |
274 | 存儲目錄,檔案將會被下載到這裏
275 |
276 |
277 | 程序將嘗試使用不高於此數值的線程下載
278 |
279 |
280 | 程序將嘗試使用不低於此數值的線程下載
281 |
282 |
283 | 超時時長(s)
284 |
285 |
286 | 采用二進制直接追加合並文件
287 |
288 |
289 | 不主動使用系統代理
290 |
291 |
292 | 不使用系統代理
293 |
294 |
295 | 不合並視頻分片
296 |
297 |
298 | 本程序生成的啟動參數
299 |
300 |
301 | M3U8地址
302 |
303 |
304 | 選擇壹個目錄,視頻將會下載到此處
305 |
306 |
307 | 找不到程式
308 |
309 |
310 | URL為必填項
311 |
312 |
313 | 請稍候
314 |
315 |
316 | 非預期的byte格式
317 |
318 |
319 | 非16 Bytes文件
320 |
321 |
322 | 輸入http/socks5代理地址,如http://127.0.0.1:8080
323 |
324 |
325 | 設置代理
326 |
327 |
328 | 不支持該代理鏈接!
329 |
330 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/Properties/Resources.en-US.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Audio Only
122 |
123 |
124 | Download all segements but only mux for audio track
125 |
126 |
127 | Set the Baseurl of the m3u8 file
128 |
129 |
130 | BinaryMerge
131 |
132 |
133 | Use binary to directly append and merge files
134 |
135 |
136 | Select
137 |
138 |
139 | Select storage directory
140 |
141 |
142 | Copy(_C)
143 |
144 |
145 | Cut(_T)
146 |
147 |
148 | DeleteAfterDone
149 |
150 |
151 | After checking this option, all segments will be deleted after the merge is completed
152 |
153 |
154 | NoIntegrityCheck
155 |
156 |
157 | After the download is complete, skip checking whether the number of segments is consistent with the number of files described in m3u8
158 |
159 |
160 | NoDateInfo
161 |
162 |
163 | Do not write the Date info when using ffmpeg muxing
164 |
165 |
166 | NoMerge
167 |
168 |
169 | Do not merge segments
170 |
171 |
172 | NoProxy
173 |
174 |
175 | Do not actively use system's proxy
176 |
177 |
178 | ToExecute
179 |
180 |
181 | Path or file name of the main program
182 |
183 |
184 | MuxFastStart
185 |
186 |
187 | Move metadata to the head when using ffmpeg muxing
188 |
189 |
190 | Get the downloader
191 |
192 |
193 | Click me to call the downloader
194 |
195 |
196 | Headers
197 |
198 |
199 | Add HTTP headers to the request
200 |
201 |
202 | SetIV
203 |
204 |
205 | Enter the HEX string
206 |
207 |
208 | SetKEY
209 |
210 |
211 | You can drag in a 16-byte local KEY file or input a Base64 string
212 |
213 |
214 | M3U8
215 |
216 |
217 | You can input or drag in file; drag into folders or txt to batch download; double click to get from the clipboard
218 |
219 |
220 | SpeedLimit
221 |
222 |
223 | Set download speed limit(kb/s); 0 means no limit
224 |
225 |
226 | MaxThread
227 |
228 |
229 | The program will try to download using threads not higher than this value
230 |
231 |
232 | MinThread
233 |
234 |
235 | The program will try to download using threads not lower than this value
236 |
237 |
238 | MuxJson
239 |
240 |
241 | You can drag in a specific json file
242 |
243 |
244 | Params
245 |
246 |
247 | Startup parameters generated by this program
248 |
249 |
250 | ParseOnly
251 |
252 |
253 | Exit the program after parsing m3u8 and only generate meta.json
254 |
255 |
256 | Paste(_P)
257 |
258 |
259 | SetRange
260 |
261 |
262 | Set the start time or start segment sequence number
263 |
264 |
265 | Set the end time or end fragment segment number
266 |
267 |
268 | RetryCount
269 |
270 |
271 | The number of times the program tries to download again when it encounters a stop speed
272 |
273 |
274 | StopSpeed
275 |
276 |
277 | When the download speed is lower than this value(kb/s) for several consecutive times, download again
278 |
279 |
280 | Timeout(s)
281 |
282 |
283 | Set the request timeout
284 |
285 |
286 | FileName
287 |
288 |
289 | Double click here to get the video title automatically
290 |
291 |
292 | Set Top
293 |
294 |
295 | Set Top most for current window
296 |
297 |
298 | WorkDir
299 |
300 |
301 | Storage directory, files will be downloaded here
302 |
303 |
304 | Choose a directory and the video will be downloaded here
305 |
306 |
307 | File not found
308 |
309 |
310 | URL is required
311 |
312 |
313 | Wait
314 |
315 |
316 | Unexpected byte format
317 |
318 |
319 | Not 16 Bytes file
320 |
321 |
322 | Set HTTP/SOCKS5 Proxy, like http://127.0.0.1:8080
323 |
324 |
325 | SetProxy
326 |
327 |
328 | Proxy is invaild!
329 |
330 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace N_m3u8DL_CLI_SimpleG.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// 一个强类型的资源类,用于查找本地化的字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | public class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// 返回此类使用的缓存的 ResourceManager 实例。
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | public static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("N_m3u8DL_CLI_SimpleG.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// 重写当前线程的 CurrentUICulture 属性,对
51 | /// 使用此强类型资源类的所有资源查找执行重写。
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | public static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// 查找类似 仅合并音频轨道 的本地化字符串。
65 | ///
66 | public static string audioOnly {
67 | get {
68 | return ResourceManager.GetString("audioOnly", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// 查找类似 下载全部分片,合并为音轨 的本地化字符串。
74 | ///
75 | public static string audioOnly_Tip {
76 | get {
77 | return ResourceManager.GetString("audioOnly_Tip", resourceCulture);
78 | }
79 | }
80 |
81 | ///
82 | /// 查找类似 设置m3u8文件的Baseurl 的本地化字符串。
83 | ///
84 | public static string baseUrl_Tip {
85 | get {
86 | return ResourceManager.GetString("baseUrl_Tip", resourceCulture);
87 | }
88 | }
89 |
90 | ///
91 | /// 查找类似 使用二进制合并 的本地化字符串。
92 | ///
93 | public static string binaryMerge {
94 | get {
95 | return ResourceManager.GetString("binaryMerge", resourceCulture);
96 | }
97 | }
98 |
99 | ///
100 | /// 查找类似 采用二进制直接追加合并文件 的本地化字符串。
101 | ///
102 | public static string binaryMerge_Tip {
103 | get {
104 | return ResourceManager.GetString("binaryMerge_Tip", resourceCulture);
105 | }
106 | }
107 |
108 | ///
109 | /// 查找类似 选择 的本地化字符串。
110 | ///
111 | public static string changeDir {
112 | get {
113 | return ResourceManager.GetString("changeDir", resourceCulture);
114 | }
115 | }
116 |
117 | ///
118 | /// 查找类似 选择存储目录 的本地化字符串。
119 | ///
120 | public static string changeDir_Tip {
121 | get {
122 | return ResourceManager.GetString("changeDir_Tip", resourceCulture);
123 | }
124 | }
125 |
126 | ///
127 | /// 查找类似 复制(_C) 的本地化字符串。
128 | ///
129 | public static string copy {
130 | get {
131 | return ResourceManager.GetString("copy", resourceCulture);
132 | }
133 | }
134 |
135 | ///
136 | /// 查找类似 剪切(_T) 的本地化字符串。
137 | ///
138 | public static string cut {
139 | get {
140 | return ResourceManager.GetString("cut", resourceCulture);
141 | }
142 | }
143 |
144 | ///
145 | /// 查找类似 合并后删除分片 的本地化字符串。
146 | ///
147 | public static string deleteAfterDone {
148 | get {
149 | return ResourceManager.GetString("deleteAfterDone", resourceCulture);
150 | }
151 | }
152 |
153 | ///
154 | /// 查找类似 勾选此项后合并完毕将删除所有分片 的本地化字符串。
155 | ///
156 | public static string deleteAfterDone_Tip {
157 | get {
158 | return ResourceManager.GetString("deleteAfterDone_Tip", resourceCulture);
159 | }
160 | }
161 |
162 | ///
163 | /// 查找类似 关闭完整性检查 的本地化字符串。
164 | ///
165 | public static string disableCheck {
166 | get {
167 | return ResourceManager.GetString("disableCheck", resourceCulture);
168 | }
169 | }
170 |
171 | ///
172 | /// 查找类似 下载完毕后跳过检查分片数量是否与m3u8内描述的文件数量一致 的本地化字符串。
173 | ///
174 | public static string disableCheck_Tip {
175 | get {
176 | return ResourceManager.GetString("disableCheck_Tip", resourceCulture);
177 | }
178 | }
179 |
180 | ///
181 | /// 查找类似 合并时不写入日期 的本地化字符串。
182 | ///
183 | public static string disableDate {
184 | get {
185 | return ResourceManager.GetString("disableDate", resourceCulture);
186 | }
187 | }
188 |
189 | ///
190 | /// 查找类似 使用ffmpeg混流时不写入Date属性 的本地化字符串。
191 | ///
192 | public static string disableDate_Tip {
193 | get {
194 | return ResourceManager.GetString("disableDate_Tip", resourceCulture);
195 | }
196 | }
197 |
198 | ///
199 | /// 查找类似 下载完成后不合并 的本地化字符串。
200 | ///
201 | public static string disableMerge {
202 | get {
203 | return ResourceManager.GetString("disableMerge", resourceCulture);
204 | }
205 | }
206 |
207 | ///
208 | /// 查找类似 不合并视频分片 的本地化字符串。
209 | ///
210 | public static string disableMerge_Tip {
211 | get {
212 | return ResourceManager.GetString("disableMerge_Tip", resourceCulture);
213 | }
214 | }
215 |
216 | ///
217 | /// 查找类似 不使用系统代理 的本地化字符串。
218 | ///
219 | public static string disableProxy {
220 | get {
221 | return ResourceManager.GetString("disableProxy", resourceCulture);
222 | }
223 | }
224 |
225 | ///
226 | /// 查找类似 不主动使用系统代理 的本地化字符串。
227 | ///
228 | public static string disableProxy_Tip {
229 | get {
230 | return ResourceManager.GetString("disableProxy_Tip", resourceCulture);
231 | }
232 | }
233 |
234 | ///
235 | /// 查找类似 执行程序 的本地化字符串。
236 | ///
237 | public static string exeToRun {
238 | get {
239 | return ResourceManager.GetString("exeToRun", resourceCulture);
240 | }
241 | }
242 |
243 | ///
244 | /// 查找类似 下载器主程序的文件名 的本地化字符串。
245 | ///
246 | public static string exeToRun_Tip {
247 | get {
248 | return ResourceManager.GetString("exeToRun_Tip", resourceCulture);
249 | }
250 | }
251 |
252 | ///
253 | /// 查找类似 混流MP4边下边看 的本地化字符串。
254 | ///
255 | public static string fastStart {
256 | get {
257 | return ResourceManager.GetString("fastStart", resourceCulture);
258 | }
259 | }
260 |
261 | ///
262 | /// 查找类似 使用ffmpeg混流时将元数据移动到头部 的本地化字符串。
263 | ///
264 | public static string fastStart_Tip {
265 | get {
266 | return ResourceManager.GetString("fastStart_Tip", resourceCulture);
267 | }
268 | }
269 |
270 | ///
271 | /// 查找类似 获取下载器(_N) 的本地化字符串。
272 | ///
273 | public static string getDL {
274 | get {
275 | return ResourceManager.GetString("getDL", resourceCulture);
276 | }
277 | }
278 |
279 | ///
280 | /// 查找类似 点击我即可调用下载器 的本地化字符串。
281 | ///
282 | public static string go_Tip {
283 | get {
284 | return ResourceManager.GetString("go_Tip", resourceCulture);
285 | }
286 | }
287 |
288 | ///
289 | /// 查找类似 请求头 的本地化字符串。
290 | ///
291 | public static string headers {
292 | get {
293 | return ResourceManager.GetString("headers", resourceCulture);
294 | }
295 | }
296 |
297 | ///
298 | /// 查找类似 为请求添加 HTTP Header 的本地化字符串。
299 | ///
300 | public static string headers_Tip {
301 | get {
302 | return ResourceManager.GetString("headers_Tip", resourceCulture);
303 | }
304 | }
305 |
306 | ///
307 | /// 查找类似 自定义IV 的本地化字符串。
308 | ///
309 | public static string iv {
310 | get {
311 | return ResourceManager.GetString("iv", resourceCulture);
312 | }
313 | }
314 |
315 | ///
316 | /// 查找类似 输入HEX字符串 的本地化字符串。
317 | ///
318 | public static string iv_Tip {
319 | get {
320 | return ResourceManager.GetString("iv_Tip", resourceCulture);
321 | }
322 | }
323 |
324 | ///
325 | /// 查找类似 自定义KEY 的本地化字符串。
326 | ///
327 | public static string key {
328 | get {
329 | return ResourceManager.GetString("key", resourceCulture);
330 | }
331 | }
332 |
333 | ///
334 | /// 查找类似 可拖入16字节的本地KEY文件或输入Base64字符串 的本地化字符串。
335 | ///
336 | public static string key_Tip {
337 | get {
338 | return ResourceManager.GetString("key_Tip", resourceCulture);
339 | }
340 | }
341 |
342 | ///
343 | /// 查找类似 M3U8地址 的本地化字符串。
344 | ///
345 | public static string m3u8 {
346 | get {
347 | return ResourceManager.GetString("m3u8", resourceCulture);
348 | }
349 | }
350 |
351 | ///
352 | /// 查找类似 可以输入或拖入文件; 拖入文件夹或txt以批量下载; 双击从剪贴板获取 的本地化字符串。
353 | ///
354 | public static string m3u8_Tip {
355 | get {
356 | return ResourceManager.GetString("m3u8_Tip", resourceCulture);
357 | }
358 | }
359 |
360 | ///
361 | /// 查找类似 限速(kb/s) 的本地化字符串。
362 | ///
363 | public static string maxSpeed {
364 | get {
365 | return ResourceManager.GetString("maxSpeed", resourceCulture);
366 | }
367 | }
368 |
369 | ///
370 | /// 查找类似 设置下载限速;0为不限制 的本地化字符串。
371 | ///
372 | public static string maxSpeed_Tip {
373 | get {
374 | return ResourceManager.GetString("maxSpeed_Tip", resourceCulture);
375 | }
376 | }
377 |
378 | ///
379 | /// 查找类似 最大线程 的本地化字符串。
380 | ///
381 | public static string maxThread {
382 | get {
383 | return ResourceManager.GetString("maxThread", resourceCulture);
384 | }
385 | }
386 |
387 | ///
388 | /// 查找类似 程序将尝试使用不高于此数值的线程下载 的本地化字符串。
389 | ///
390 | public static string maxThread_Tip {
391 | get {
392 | return ResourceManager.GetString("maxThread_Tip", resourceCulture);
393 | }
394 | }
395 |
396 | ///
397 | /// 查找类似 最小线程 的本地化字符串。
398 | ///
399 | public static string minThread {
400 | get {
401 | return ResourceManager.GetString("minThread", resourceCulture);
402 | }
403 | }
404 |
405 | ///
406 | /// 查找类似 程序将尝试使用不低于此数值的线程下载 的本地化字符串。
407 | ///
408 | public static string minThread_Tip {
409 | get {
410 | return ResourceManager.GetString("minThread_Tip", resourceCulture);
411 | }
412 | }
413 |
414 | ///
415 | /// 查找类似 混流文件 的本地化字符串。
416 | ///
417 | public static string muxJson {
418 | get {
419 | return ResourceManager.GetString("muxJson", resourceCulture);
420 | }
421 | }
422 |
423 | ///
424 | /// 查找类似 可拖入特定的json文件 的本地化字符串。
425 | ///
426 | public static string muxJson_Tip {
427 | get {
428 | return ResourceManager.GetString("muxJson_Tip", resourceCulture);
429 | }
430 | }
431 |
432 | ///
433 | /// 查找类似 启动参数 的本地化字符串。
434 | ///
435 | public static string parm {
436 | get {
437 | return ResourceManager.GetString("parm", resourceCulture);
438 | }
439 | }
440 |
441 | ///
442 | /// 查找类似 本程序生成的启动参数 的本地化字符串。
443 | ///
444 | public static string parm_Tip {
445 | get {
446 | return ResourceManager.GetString("parm_Tip", resourceCulture);
447 | }
448 | }
449 |
450 | ///
451 | /// 查找类似 仅解析m3u8 的本地化字符串。
452 | ///
453 | public static string parseOnly {
454 | get {
455 | return ResourceManager.GetString("parseOnly", resourceCulture);
456 | }
457 | }
458 |
459 | ///
460 | /// 查找类似 在解析m3u8之后退出程序,仅生成meta.json 的本地化字符串。
461 | ///
462 | public static string parseOnly_Tip {
463 | get {
464 | return ResourceManager.GetString("parseOnly_Tip", resourceCulture);
465 | }
466 | }
467 |
468 | ///
469 | /// 查找类似 粘贴(_P) 的本地化字符串。
470 | ///
471 | public static string paste {
472 | get {
473 | return ResourceManager.GetString("paste", resourceCulture);
474 | }
475 | }
476 |
477 | ///
478 | /// 查找类似 范围选择 的本地化字符串。
479 | ///
480 | public static string range {
481 | get {
482 | return ResourceManager.GetString("range", resourceCulture);
483 | }
484 | }
485 |
486 | ///
487 | /// 查找类似 设置开始时间或开始分片序号 的本地化字符串。
488 | ///
489 | public static string range_Tip1 {
490 | get {
491 | return ResourceManager.GetString("range_Tip1", resourceCulture);
492 | }
493 | }
494 |
495 | ///
496 | /// 查找类似 设置终止时间或终止分片序号 的本地化字符串。
497 | ///
498 | public static string range_Tip2 {
499 | get {
500 | return ResourceManager.GetString("range_Tip2", resourceCulture);
501 | }
502 | }
503 |
504 | ///
505 | /// 查找类似 重试次数 的本地化字符串。
506 | ///
507 | public static string retryCount {
508 | get {
509 | return ResourceManager.GetString("retryCount", resourceCulture);
510 | }
511 | }
512 |
513 | ///
514 | /// 查找类似 遇到停止速度时,程序尝试重新下载的次数 的本地化字符串。
515 | ///
516 | public static string retryCount_Tip {
517 | get {
518 | return ResourceManager.GetString("retryCount_Tip", resourceCulture);
519 | }
520 | }
521 |
522 | ///
523 | /// 查找类似 设置代理 的本地化字符串。
524 | ///
525 | public static string setProxy {
526 | get {
527 | return ResourceManager.GetString("setProxy", resourceCulture);
528 | }
529 | }
530 |
531 | ///
532 | /// 查找类似 输入http/socks5代理地址,如http://127.0.0.1:8080. 的本地化字符串。
533 | ///
534 | public static string setProxy_Tip {
535 | get {
536 | return ResourceManager.GetString("setProxy_Tip", resourceCulture);
537 | }
538 | }
539 |
540 | ///
541 | /// 查找类似 停速(kb/s) 的本地化字符串。
542 | ///
543 | public static string stopSpeed {
544 | get {
545 | return ResourceManager.GetString("stopSpeed", resourceCulture);
546 | }
547 | }
548 |
549 | ///
550 | /// 查找类似 当下载速度连续几次低于此数值时,重新下载 的本地化字符串。
551 | ///
552 | public static string stopSpeed_Tip {
553 | get {
554 | return ResourceManager.GetString("stopSpeed_Tip", resourceCulture);
555 | }
556 | }
557 |
558 | ///
559 | /// 查找类似 选择一个目录,视频将会下载到此处 的本地化字符串。
560 | ///
561 | public static string String1 {
562 | get {
563 | return ResourceManager.GetString("String1", resourceCulture);
564 | }
565 | }
566 |
567 | ///
568 | /// 查找类似 找不到程序 的本地化字符串。
569 | ///
570 | public static string String2 {
571 | get {
572 | return ResourceManager.GetString("String2", resourceCulture);
573 | }
574 | }
575 |
576 | ///
577 | /// 查找类似 URL为必填项 的本地化字符串。
578 | ///
579 | public static string String3 {
580 | get {
581 | return ResourceManager.GetString("String3", resourceCulture);
582 | }
583 | }
584 |
585 | ///
586 | /// 查找类似 请稍候 的本地化字符串。
587 | ///
588 | public static string String4 {
589 | get {
590 | return ResourceManager.GetString("String4", resourceCulture);
591 | }
592 | }
593 |
594 | ///
595 | /// 查找类似 非预期的byte格式 的本地化字符串。
596 | ///
597 | public static string String5 {
598 | get {
599 | return ResourceManager.GetString("String5", resourceCulture);
600 | }
601 | }
602 |
603 | ///
604 | /// 查找类似 非16 Bytes文件 的本地化字符串。
605 | ///
606 | public static string String6 {
607 | get {
608 | return ResourceManager.GetString("String6", resourceCulture);
609 | }
610 | }
611 |
612 | ///
613 | /// 查找类似 不支持该代理链接! 的本地化字符串。
614 | ///
615 | public static string String7 {
616 | get {
617 | return ResourceManager.GetString("String7", resourceCulture);
618 | }
619 | }
620 |
621 | ///
622 | /// 查找类似 超时时长(s) 的本地化字符串。
623 | ///
624 | public static string timeout {
625 | get {
626 | return ResourceManager.GetString("timeout", resourceCulture);
627 | }
628 | }
629 |
630 | ///
631 | /// 查找类似 设置请求超时时长 的本地化字符串。
632 | ///
633 | public static string timeout_Tip {
634 | get {
635 | return ResourceManager.GetString("timeout_Tip", resourceCulture);
636 | }
637 | }
638 |
639 | ///
640 | /// 查找类似 视频标题 的本地化字符串。
641 | ///
642 | public static string title {
643 | get {
644 | return ResourceManager.GetString("title", resourceCulture);
645 | }
646 | }
647 |
648 | ///
649 | /// 查找类似 双击此处可以自动获取视频标题 的本地化字符串。
650 | ///
651 | public static string title_Tip {
652 | get {
653 | return ResourceManager.GetString("title_Tip", resourceCulture);
654 | }
655 | }
656 |
657 | ///
658 | /// 查找类似 置顶窗口 的本地化字符串。
659 | ///
660 | public static string topMost {
661 | get {
662 | return ResourceManager.GetString("topMost", resourceCulture);
663 | }
664 | }
665 |
666 | ///
667 | /// 查找类似 置顶当前窗口 的本地化字符串。
668 | ///
669 | public static string topMost_Tip {
670 | get {
671 | return ResourceManager.GetString("topMost_Tip", resourceCulture);
672 | }
673 | }
674 |
675 | ///
676 | /// 查找类似 工作目录 的本地化字符串。
677 | ///
678 | public static string workDir {
679 | get {
680 | return ResourceManager.GetString("workDir", resourceCulture);
681 | }
682 | }
683 |
684 | ///
685 | /// 查找类似 存储目录,文件将会被下载到这里 的本地化字符串。
686 | ///
687 | public static string workDir_Tip {
688 | get {
689 | return ResourceManager.GetString("workDir_Tip", resourceCulture);
690 | }
691 | }
692 | }
693 | }
694 |
--------------------------------------------------------------------------------
/N_m3u8DL-CLI-SimpleG/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Net.Security;
8 | using System.Security.Cryptography.X509Certificates;
9 | using System.Text;
10 | using System.Text.RegularExpressions;
11 | using System.Threading;
12 | using System.Threading.Tasks;
13 | using System.Windows;
14 | using System.Windows.Controls;
15 | using System.Windows.Data;
16 | using System.Windows.Documents;
17 | using System.Windows.Forms;
18 | using System.Windows.Input;
19 | using System.Windows.Media;
20 | using System.Windows.Media.Animation;
21 | using System.Windows.Media.Imaging;
22 | using System.Windows.Navigation;
23 | using System.Windows.Shapes;
24 | using System.Windows.Threading;
25 | using Application = System.Windows.Application;
26 | using Button = System.Windows.Controls.Button;
27 | using Clipboard = System.Windows.Clipboard;
28 | using DataFormats = System.Windows.DataFormats;
29 | using DragDropEffects = System.Windows.DragDropEffects;
30 | using MessageBox = System.Windows.MessageBox;
31 | using Path = System.IO.Path;
32 | using TextBox = System.Windows.Controls.TextBox;
33 |
34 | namespace N_m3u8DL_CLI_SimpleG
35 | {
36 | ///
37 | /// MainWindow.xaml 的交互逻辑
38 | ///
39 | /// 2019年6月17日
40 | /// - 重构界面并修复爱奇艺标题获取BUG
41 | /// 2019年6月18日
42 | /// - 添加图标
43 | /// 2019年6月23日
44 | /// - 调整寻找主程序的逻辑
45 | /// - 修改匹配URL的正则表达式
46 | /// - 启动时自动匹配URL并识别标题
47 | /// - 启动后M3U8地址文本框会自动获得焦点
48 | /// - M3U8地址和标题两个文本框能够响应回车事件
49 | /// - GO按钮点击可以使用ALT+S快捷键来触发
50 | /// 2019年7月24日
51 | /// - 优化获取视频标题的逻辑
52 | /// - 增加生成--downloadRange参数
53 | /// 2019年8月11日
54 | /// - 批量txt支持自定义文件名
55 | /// 2019年8月17日
56 | /// - 支持爱奇艺dash链接直接下载
57 | /// - 修复腾讯视频标题获取bug
58 | /// 2019年9月18日
59 | /// - 支持限速
60 | /// - 全新界面
61 | /// - 增加控件悬浮提示
62 | /// 2019年9月28日
63 | /// - 双击时判断URL是否一致再赋值
64 | /// - 细节优化
65 | /// 2019年10月9日
66 | /// - 自动获取文件编码
67 | /// 2019年10月24日
68 | /// - 请求dash链接时尝试读取iqiyicookie.txt
69 | /// 2019年12月16日
70 | /// - 批量读取txt跳过空白行
71 | /// - 腾讯Unicode转换
72 | /// 2020年2月1日
73 | /// - 修复部分wetv无法识别标题的问题
74 | /// 2020年2月17日
75 | /// - 拖入meta.json自动命名
76 | /// - 拖入KEY文件校验是否正确
77 | /// - 可调节大小
78 | /// 2020年4月17日
79 | /// - 修改BAT为UTF-8编码
80 | /// - 细微优化
81 | /// 2020年11月21日
82 | /// - 修正UI
83 | /// 2021年1月24日
84 | /// - 支持简繁英多语言
85 | /// 2021年3月4日
86 | /// - 支持设置代理
87 | /// - 支持存储代理、请求头
88 | /// 2021年3月21日
89 | /// - 支持MPD批量
90 | ///
91 | public partial class MainWindow : Window
92 | {
93 | //用于证书验证
94 | public static bool CertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
95 | {
96 | X509Chain verify = new X509Chain();
97 | verify.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
98 | verify.ChainPolicy.RevocationMode = X509RevocationMode.Online; //revocation checking
99 | verify.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
100 | if (verify.Build(new X509Certificate2(certificate)))
101 | {
102 | return true;
103 | }
104 | return false;
105 | }
106 |
107 | public MainWindow()
108 | {
109 | InitializeComponent();
110 | TextBox_URL.Focus();
111 | }
112 |
113 | private void Button_SelectDir_Click(object sender, RoutedEventArgs e)
114 | {
115 | FolderBrowserDialog openFileDialog = new FolderBrowserDialog(); //选择文件夹
116 | openFileDialog.Description = Properties.Resources.String1;
117 | if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
118 | {
119 | TextBox_WorkDir.Text = openFileDialog.SelectedPath;
120 | }
121 | }
122 |
123 | private void GetParameter()
124 | {
125 | if (TextBox_Parameter == null)
126 | return;
127 |
128 | StringBuilder sb = new StringBuilder();
129 | sb.Append("\"" + TextBox_URL.Text + "\" ");
130 | if (!string.IsNullOrEmpty(TextBox_WorkDir.Text))
131 | {
132 | if (TextBox_WorkDir.Text.Trim('\\').EndsWith(":")) //根目录
133 | {
134 | sb.Append("--workDir \"" + TextBox_WorkDir.Text.Trim('\\') + "\\\\" + "\" ");
135 | }
136 | else
137 | {
138 | sb.Append("--workDir \"" + TextBox_WorkDir.Text.Trim('\\') + "\" ");
139 | }
140 | }
141 | if (!string.IsNullOrEmpty(TextBox_Title.Text))
142 | sb.Append("--saveName \"" + TextBox_Title.Text + "\" ");
143 | if (!string.IsNullOrEmpty(TextBox_Headers.Text))
144 | sb.Append("--headers \"" + TextBox_Headers.Text + "\" ");
145 | if (!string.IsNullOrEmpty(TextBox_Baseurl.Text))
146 | sb.Append("--baseUrl \"" + TextBox_Baseurl.Text + "\" ");
147 | if (!string.IsNullOrEmpty(TextBox_MuxJson.Text))
148 | sb.Append("--muxSetJson \"" + TextBox_MuxJson.Text + "\" ");
149 | if (TextBox_Max.Text != "32")
150 | sb.Append("--maxThreads \"" + TextBox_Max.Text + "\" ");
151 | if (TextBox_Min.Text != "16")
152 | sb.Append("--minThreads \"" + TextBox_Min.Text + "\" ");
153 | if (TextBox_Retry.Text != "15")
154 | sb.Append("--retryCount \"" + TextBox_Retry.Text + "\" ");
155 | if (TextBox_Timeout.Text != "10")
156 | sb.Append("--timeOut \"" + TextBox_Timeout.Text + "\" ");
157 | if (TextBox_StopSpeed.Text != "0")
158 | sb.Append("--stopSpeed \"" + TextBox_StopSpeed.Text + "\" ");
159 | if (TextBox_MaxSpeed.Text != "0")
160 | sb.Append("--maxSpeed \"" + TextBox_MaxSpeed.Text + "\" ");
161 | if (TextBox_Key.Text != "")
162 | {
163 | if (File.Exists(TextBox_Key.Text))
164 | sb.Append("--useKeyFile \"" + TextBox_Key.Text + "\" ");
165 | else
166 | sb.Append("--useKeyBase64 \"" + TextBox_Key.Text + "\" ");
167 | }
168 | if (TextBox_IV.Text != "")
169 | {
170 | sb.Append("--useKeyIV \"" + TextBox_IV.Text + "\" ");
171 | }
172 | if (TextBox_Proxy.Text != "")
173 | {
174 | sb.Append("--proxyAddress \"" + TextBox_Proxy.Text.Trim() + "\" ");
175 | }
176 | if (CheckBox_Del.IsChecked == true)
177 | sb.Append("--enableDelAfterDone ");
178 | if (CheckBox_FastStart.IsChecked == true)
179 | sb.Append("--enableMuxFastStart ");
180 | if (CheckBox_BinaryMerge.IsChecked == true)
181 | sb.Append("--enableBinaryMerge ");
182 | if (CheckBox_ParserOnly.IsChecked == true)
183 | sb.Append("--enableParseOnly ");
184 | if (CheckBox_DisableDate.IsChecked == true)
185 | sb.Append("--disableDateInfo ");
186 | if (CheckBox_DisableMerge.IsChecked == true)
187 | sb.Append("--noMerge ");
188 | if (CheckBox_DisableProxy.IsChecked == true)
189 | sb.Append("--noProxy ");
190 | if (CheckBox_DisableCheck.IsChecked == true)
191 | sb.Append("--disableIntegrityCheck ");
192 | if (CheckBox_AudioOnly.IsChecked == true)
193 | sb.Append("--enableAudioOnly ");
194 | if (TextBox_RangeStart.Text!="00:00:00"|| TextBox_RangeEnd.Text != "00:00:00")
195 | {
196 | sb.Append($"--downloadRange \"{TextBox_RangeStart.Text}-{TextBox_RangeEnd.Text}\"");
197 | }
198 |
199 | TextBox_Parameter.Text = sb.ToString();
200 | }
201 |
202 | private void TextChanged(object sender, TextChangedEventArgs e)
203 | {
204 | GetParameter();
205 | }
206 |
207 | private void CheckBoxChanged(object sender, RoutedEventArgs e)
208 | {
209 | if (((System.Windows.Controls.CheckBox)sender).IsChecked == true)
210 | {
211 | ((System.Windows.Controls.CheckBox)sender).Foreground = new SolidColorBrush(Color.FromRgb(46, 204, 113));
212 | }
213 | else
214 | {
215 | ((System.Windows.Controls.CheckBox)sender).Foreground = new SolidColorBrush(Color.FromRgb(241, 241, 241));
216 | }
217 | GetParameter();
218 | }
219 |
220 | private void FlashTextBox(TextBox textBox)
221 | {
222 | var orgColor = textBox.Background;
223 | SolidColorBrush myBrush = new SolidColorBrush();
224 | ColorAnimation myColorAnimation = new ColorAnimation();
225 | myColorAnimation.To = (Color)ColorConverter.ConvertFromString("#2ecc71");
226 | myColorAnimation.Duration = TimeSpan.FromMilliseconds(300);
227 | myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation, HandoffBehavior.Compose);
228 | textBox.Background = myBrush;
229 |
230 | myColorAnimation.To = (Color)ColorConverter.ConvertFromString(orgColor.ToString());
231 | myColorAnimation.Duration = TimeSpan.FromMilliseconds(1000);
232 | myBrush.BeginAnimation(SolidColorBrush.ColorProperty, myColorAnimation, HandoffBehavior.Compose);
233 | textBox.Background = myBrush;
234 | }
235 |
236 | private void TextBox_URL_MouseDoubleClick(object sender, MouseButtonEventArgs e)
237 | {
238 | //从剪切板读取url
239 | Regex url = new Regex(@"(https?)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]", RegexOptions.Compiled | RegexOptions.Singleline);//取已下载大小
240 | string str = url.Match(Clipboard.GetText()).Value;
241 | if (str != "" && str != TextBox_URL.Text)
242 | {
243 | TextBox_URL.Text = str;
244 | FlashTextBox(TextBox_URL);
245 | }
246 | }
247 |
248 | public static byte[] HexStringToBytes(string hexStr)
249 | {
250 | if (string.IsNullOrEmpty(hexStr))
251 | {
252 | return new byte[0];
253 | }
254 |
255 | if (hexStr.StartsWith("0x") || hexStr.StartsWith("0X"))
256 | {
257 | hexStr = hexStr.Remove(0, 2);
258 | }
259 |
260 | int count = hexStr.Length;
261 |
262 | if (count % 2 == 1)
263 | {
264 | throw new ArgumentException("Invalid length of bytes:" + count);
265 | }
266 |
267 | int byteCount = count / 2;
268 | byte[] result = new byte[byteCount];
269 | for (int ii = 0; ii < byteCount; ++ii)
270 | {
271 | var tempBytes = Byte.Parse(hexStr.Substring(2 * ii, 2), System.Globalization.NumberStyles.HexNumber);
272 | result[ii] = tempBytes;
273 | }
274 |
275 | return result;
276 | }
277 |
278 | private string GetTitleFromURL(string url)
279 | {
280 | try
281 | {
282 | if (File.Exists(url))
283 | return Path.GetFileNameWithoutExtension(url);
284 | if (url.StartsWith("http"))
285 | url = url.Replace("http://", "").Replace("https://", "");
286 | //从爱奇艺dash接口获取内容
287 | if (url.Contains("dash") && (url.StartsWith("cache.video.iqiyi.com") || url.StartsWith("intel-cache.video.iqiyi.com")))
288 | {
289 | string tvid = GetQueryString("tvid", url);
290 | string webSource = GetWebSource($"https://pcw-api.iqiyi.com/video/video/baseinfo/{tvid}");
291 | Regex rexTitle = new Regex("name\":\"(.*?)\"");
292 | string title = GetValidFileName(rexTitle.Match(webSource).Groups[1].Value);
293 |
294 | webSource = GetWebSource("https://" + url, "Cookie:" + (File.Exists("iqiyicookie.txt") ? File.ReadAllText("iqiyicookie.txt").Trim() : ""));
295 | string[] videoes = new Regex("\"video\"[\\s\\S]*").Match(webSource).Value.Replace("},{", "|").Split('|');
296 | string size = "";
297 | string m3u8Content = "";
298 | string code = "";
299 | string duration = "";
300 | string scrsz = "";
301 | string fileName = "";
302 | string filePath = "";
303 | foreach (var video in videoes)
304 | {
305 | if (video.Contains("\"_selected\":true"))
306 | {
307 | size = FormatFileSize(Convert.ToDouble(new Regex("\"vsize\":(\\d+)").Match(video).Groups[1].Value));
308 | m3u8Content = new Regex("\"m3u8\":\"(.*?)\"").Match(video).Groups[1].Value.Replace("\\n", "\n").Replace("\\/", "/");
309 | code = new Regex("\"code\":(\\d+)").Match(video).Groups[1].Value;
310 | duration = FormatTime(Convert.ToInt32(new Regex("\"duration\":(\\d+)").Match(video).Groups[1].Value));
311 | scrsz = new Regex("\"scrsz\":\"(.*?)\"").Match(video).Groups[1].Value;
312 | fileName = title + "_" + scrsz + "_" + (code == "2" ? "H264" : "H265") + "_" + duration + "_" + size;
313 | filePath = Path.Combine(Path.GetTempPath(), fileName + ".m3u8");
314 | break;
315 | }
316 | }
317 | File.WriteAllText(filePath, m3u8Content);
318 | TextBox_URL.Text = filePath;
319 | return GetValidFileName(fileName);
320 | }
321 | else if (url.StartsWith("cache.m.iqiyi.com"))
322 | {
323 | string tvid = GetQueryString("tvid", url);
324 | string webSource = GetWebSource($"https://pcw-api.iqiyi.com/video/video/baseinfo/{tvid}");
325 | Regex rexTitle = new Regex("name\":\"(.*?)\"");
326 | Regex rexDur = new Regex("duration\":\"(.*?)\"");
327 | string title = rexTitle.Match(webSource).Groups[1].Value
328 | + "_"
329 | + rexDur.Match(webSource).Groups[1].Value;
330 | //获得有效文件名
331 | return GetValidFileName(title);
332 | }
333 | else if (url.Contains("ccode=") && url.Contains("vid="))
334 | {
335 | string vid = GetQueryString("vid", url);
336 | string webSource = GetWebSource($"https://openapi.youku.com/v2/videos/show.json?video_id={vid}&client_id=3d01f04416cbe807");
337 | Regex rexTitle = new Regex("title\":\"(.*?)\"");
338 | Regex rexDur = new Regex("duration\":\"(.*?)\"");
339 | string type = GetQueryString("type", url);
340 | string title = Unicode2String(rexTitle.Match(webSource).Groups[1].Value)
341 | + "_"
342 | + FormatTime((int)Convert.ToDouble(rexDur.Match(webSource).Groups[1].Value));
343 | if (type != "")
344 | title += "_" + type;
345 | return GetValidFileName(title);
346 | }
347 | else if ((url.Contains(".ts.m3u8") || url.Contains(".mp4.m3u8")) && url.Contains("qq.com"))
348 | {
349 | Regex rexVid = new Regex("\\/(\\w+).(\\d){6,}.*m3u8");
350 | string match = rexVid.Match(url).Groups[1].Value;
351 | string vid = "";
352 | if (match.Contains("_"))
353 | vid = match.Split('_')[1];
354 | else
355 | vid = match;
356 |
357 | return GetValidFileName(GetQQTitle(vid));
358 | }
359 | else
360 | {
361 | return GetUrlFileName(url);
362 | }
363 | }
364 | catch (Exception)
365 | {
366 | return DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss");
367 | }
368 | }
369 |
370 | public static string GetQQTitle(string vid)
371 | {
372 | Regex rexTitle1 = new Regex("\"title\":(.*?),");
373 | Regex rexDur = new Regex("duration\":\"(.*?)\"");
374 | string webSource = GetWebSource($"https://union.video.qq.com/fcgi-bin/data?tid=682&otype=json&appid=20001373&appkey=f6301da6035cd6cc&client=tim&idlist={vid}");
375 | string title = "";
376 |
377 | if (rexTitle1.Match(webSource).Groups[1].Value.Trim('\"') != "null")
378 | {
379 | string t = rexTitle1.Match(webSource).Groups[1].Value.Trim('\"');
380 | if (t.Contains("\\u"))
381 | t = Unicode2String(t);
382 | title = t
383 | + "_"
384 | + FormatTime(Convert.ToInt32(rexDur.Match(webSource).Groups[1].Value));
385 | return title;
386 | }
387 | else
388 | {
389 | Regex rexTitle = new Regex("\"ti\":\"(.*?)\"");
390 | webSource = GetWebSource($"https://vv.video.qq.com/getinfo?otype=json&appver=3.4.40&platform=4830701&vid={vid}");
391 | title = rexTitle.Match(webSource).Groups[1].Value;
392 | if (title.Contains("\\u"))
393 | title = Unicode2String(title);
394 | if (string.IsNullOrEmpty(title))
395 | {
396 | rexTitle = new Regex("VIDEO_INFO.*\"title\":\"(.*?)\"");
397 | webSource = new WebClient() { Encoding = Encoding.UTF8 }.DownloadString($"https://v.qq.com/x/page/{vid}.html");
398 | title = rexTitle.Match(webSource).Groups[1].Value;
399 | return title;
400 | }
401 | else
402 | return title;
403 | }
404 | }
405 |
406 | //获取网页源码
407 | private static string GetWebSource(String url, string headers = "", int TimeOut = 60000)
408 | {
409 | ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallback;
410 | //Init时执行,用于注册方法。
411 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3
412 | | SecurityProtocolType.Tls
413 | | (SecurityProtocolType)0x300 //Tls11
414 | | (SecurityProtocolType)0xC00; //Tls12
415 | string htmlCode = string.Empty;
416 | try
417 | {
418 | HttpWebRequest webRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
419 | webRequest.Method = "GET";
420 | webRequest.UserAgent = "Mozilla/4.0";
421 | webRequest.Headers.Add("Accept-Encoding", "gzip, deflate");
422 | webRequest.Timeout = TimeOut; //设置超时
423 | webRequest.KeepAlive = false;
424 | //添加headers
425 | if (headers != "")
426 | {
427 | foreach (string att in headers.Split('|'))
428 | {
429 | try
430 | {
431 | if (att.Split(':')[0].ToLower() == "referer")
432 | webRequest.Referer = att.Substring(att.IndexOf(":") + 1);
433 | else if (att.Split(':')[0].ToLower() == "user-agent")
434 | webRequest.UserAgent = att.Substring(att.IndexOf(":") + 1);
435 | else if (att.Split(':')[0].ToLower() == "range")
436 | webRequest.AddRange(Convert.ToInt32(att.Substring(att.IndexOf(":") + 1).Split('-')[0], Convert.ToInt32(att.Substring(att.IndexOf(":") + 1).Split('-')[1])));
437 | else if (att.Split(':')[0].ToLower() == "accept")
438 | webRequest.Accept = att.Substring(att.IndexOf(":") + 1);
439 | else
440 | webRequest.Headers.Add(att);
441 | }
442 | catch (Exception e)
443 | {
444 |
445 | }
446 | }
447 | }
448 | HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
449 | if (webResponse.ContentEncoding != null
450 | && webResponse.ContentEncoding.ToLower() == "gzip") //如果使用了GZip则先解压
451 | {
452 | using (Stream streamReceive = webResponse.GetResponseStream())
453 | {
454 | using (var zipStream =
455 | new System.IO.Compression.GZipStream(streamReceive, System.IO.Compression.CompressionMode.Decompress))
456 | {
457 | using (StreamReader sr = new StreamReader(zipStream, Encoding.UTF8))
458 | {
459 | htmlCode = sr.ReadToEnd();
460 | }
461 | }
462 | }
463 | }
464 | else
465 | {
466 | using (Stream streamReceive = webResponse.GetResponseStream())
467 | {
468 | using (StreamReader sr = new StreamReader(streamReceive, Encoding.UTF8))
469 | {
470 | htmlCode = sr.ReadToEnd();
471 | }
472 | }
473 | }
474 |
475 | if (webResponse != null)
476 | {
477 | webResponse.Close();
478 | }
479 | if (webRequest != null)
480 | {
481 | webRequest.Abort();
482 | }
483 | }
484 | catch (Exception e) //捕获所有异常
485 | {
486 |
487 | }
488 |
489 | return htmlCode;
490 | }
491 |
492 | ///
493 | /// Unicode转字符串
494 | ///
495 | /// 经过Unicode编码的字符串
496 | /// 正常字符串
497 | public static string Unicode2String(string source)
498 | {
499 | return new Regex(@"\\u([0-9A-F]{4})", RegexOptions.IgnoreCase | RegexOptions.Compiled).Replace(
500 | source, x => string.Empty + Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16)));
501 | }
502 |
503 | ///
504 | /// 获取url字符串参数,返回参数值字符串
505 | ///
506 | /// 参数名称
507 | /// url字符串
508 | ///
509 | public string GetQueryString(string name, string url)
510 | {
511 | Regex re = new Regex(@"(^|&)?(\w+)=([^&]+)(&|$)?", System.Text.RegularExpressions.RegexOptions.Compiled);
512 | MatchCollection mc = re.Matches(url);
513 | foreach (Match m in mc)
514 | {
515 | if (m.Result("$2").Equals(name))
516 | {
517 | return m.Result("$3");
518 | }
519 | }
520 | return "";
521 | }
522 |
523 | private void TextBox_Title_MouseDoubleClick(object sender, MouseButtonEventArgs e)
524 | {
525 | if (TextBox_URL.Text != "")
526 | TextBox_Title.Text = GetTitleFromURL(TextBox_URL.Text);
527 | }
528 |
529 |
530 | //寻找cookie字符串中的value
531 | public static string FindCookie(string key, string cookie)
532 | {
533 | string[] values = cookie.Split(';');
534 | string value = "";
535 | foreach (var v in values)
536 | {
537 | if (v.Trim().StartsWith(key + "="))
538 | value = v.Remove(0, v.IndexOf('=') + 1).Trim();
539 | }
540 | return value;
541 | }
542 |
543 | //此函数用于格式化输出时长
544 | public static String FormatTime(Int32 time)
545 | {
546 | TimeSpan ts = new TimeSpan(0, 0, time);
547 | string str = "";
548 | str = (ts.Hours.ToString("00") == "00" ? "" : ts.Hours.ToString("00") + ".") + ts.Minutes.ToString("00") + "." + ts.Seconds.ToString("00");
549 | return str;
550 | }
551 |
552 | //此函数用于格式化输出文件大小
553 | public static String FormatFileSize(Double fileSize)
554 | {
555 | if (fileSize < 0)
556 | {
557 | throw new ArgumentOutOfRangeException("fileSize");
558 | }
559 | else if (fileSize >= 1024 * 1024 * 1024)
560 | {
561 | return string.Format("{0:########0.00}GB", ((Double)fileSize) / (1024 * 1024 * 1024));
562 | }
563 | else if (fileSize >= 1024 * 1024)
564 | {
565 | return string.Format("{0:####0.00}MB", ((Double)fileSize) / (1024 * 1024));
566 | }
567 | else if (fileSize >= 1024)
568 | {
569 | return string.Format("{0:####0.00}KB", ((Double)fileSize) / 1024);
570 | }
571 | else
572 | {
573 | return string.Format("{0}bytes", fileSize);
574 | }
575 | }
576 |
577 | public static string GetUrlFileName(string url)
578 | {
579 | if (string.IsNullOrEmpty(url))
580 | {
581 | return "None";
582 | }
583 | try
584 | {
585 | string[] strs1 = url.Split(new char[] { '/' });
586 | return GetValidFileName(System.Web.HttpUtility.UrlDecode(strs1[strs1.Length - 1].Split(new char[] { '?' })[0].Replace(".m3u8", "")));
587 | }
588 | catch (Exception)
589 | {
590 | return DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss");
591 | }
592 | }
593 |
594 | public static string GetValidFileName(string input, string re = ".")
595 | {
596 | string title = input;
597 | foreach (char invalidChar in Path.GetInvalidFileNameChars())
598 | {
599 | title = title.Replace(invalidChar.ToString(), re);
600 | }
601 | return title;
602 | }
603 |
604 | private void TextBox_URL_PreviewDragOver(object sender, System.Windows.DragEventArgs e)
605 | {
606 | e.Effects = DragDropEffects.Copy;
607 | e.Handled = true;
608 | }
609 |
610 | private void TextBox_URL_PreviewDragEnter(object sender, System.Windows.DragEventArgs e)
611 | {
612 | e.Effects = DragDropEffects.Copy;
613 | e.Handled = true;
614 | }
615 |
616 | private void TextBox_URL_PreviewDrop(object sender, System.Windows.DragEventArgs e)
617 | {
618 | if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
619 | {
620 | //获取拖拽的文件地址
621 | var filenames = (string[])e.Data.GetData(DataFormats.FileDrop);
622 | var hz = filenames[0].LastIndexOf('.') + 1;
623 | var houzhui = filenames[0].Substring(hz).ToLower();//文件后缀名
624 | string path = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
625 | if (houzhui == "m3u8" || houzhui == "txt" || houzhui == "json" || houzhui == "mpd") //只允许拖入部分文件
626 | {
627 | e.Effects = DragDropEffects.Copy;
628 | e.Handled = true;
629 | if (TextBox_URL.Text != path) FlashTextBox(TextBox_URL);
630 | TextBox_URL.Text = path; //将获取到的完整路径赋值到textBox1
631 | if (houzhui == "m3u8" || houzhui == "json" || houzhui == "mpd")
632 | TextBox_Title.Text = Path.GetFileNameWithoutExtension(path); //自动获取文件名
633 | }
634 | if (Directory.Exists(path))
635 | {
636 | if (TextBox_URL.Text != path) FlashTextBox(TextBox_URL);
637 | TextBox_URL.Text = path;
638 | }
639 | }
640 | }
641 |
642 | private void TextBox_MuxJson_PreviewDragEnter(object sender, System.Windows.DragEventArgs e)
643 | {
644 | e.Effects = DragDropEffects.Copy;
645 | e.Handled = true;
646 | }
647 |
648 | private void TextBox_MuxJson_PreviewDragOver(object sender, System.Windows.DragEventArgs e)
649 | {
650 | e.Effects = DragDropEffects.Copy;
651 | e.Handled = true;
652 | }
653 |
654 | private void TextBox_MuxJson_PreviewDrop(object sender, System.Windows.DragEventArgs e)
655 | {
656 | if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
657 | {
658 | //获取拖拽的文件地址
659 | var filenames = (string[])e.Data.GetData(DataFormats.FileDrop);
660 | var hz = filenames[0].LastIndexOf('.') + 1;
661 | var houzhui = filenames[0].Substring(hz).ToLower();//文件后缀名
662 | string path = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
663 | if (houzhui == "json") //只允许拖入部分文件
664 | {
665 | e.Effects = DragDropEffects.Copy;
666 | e.Handled = true;
667 | TextBox_MuxJson.Text = path; //将获取到的完整路径赋值到textBox1
668 | }
669 | }
670 | }
671 |
672 | private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
673 | {
674 | //string to base64
675 | Encoding encode = Encoding.UTF8;
676 | byte[] bytedata = encode.GetBytes(TextBox_EXE.Text);
677 | string exePath = Convert.ToBase64String(bytedata, 0, bytedata.Length);
678 | bytedata = encode.GetBytes(TextBox_WorkDir.Text);
679 | string saveDir = Convert.ToBase64String(bytedata, 0, bytedata.Length);
680 | bytedata = encode.GetBytes(TextBox_Proxy.Text);
681 | string proxy = Convert.ToBase64String(bytedata, 0, bytedata.Length);
682 | bytedata = encode.GetBytes(TextBox_Headers.Text);
683 | string headers = Convert.ToBase64String(bytedata, 0, bytedata.Length);
684 |
685 | string config = "程序路径=" + exePath
686 | + ";保存路径=" + saveDir
687 | + ";代理=" + proxy
688 | + ";请求头=" + headers
689 | + ";删除临时文件=" + (CheckBox_Del.IsChecked == true ? "1" : "0")
690 | + ";MP4混流边下边看=" + (CheckBox_FastStart.IsChecked == true ? "1" : "0")
691 | + ";二进制合并=" + (CheckBox_BinaryMerge.IsChecked == true ? "1" : "0")
692 | + ";仅解析模式=" + (CheckBox_ParserOnly.IsChecked == true ? "1" : "0")
693 | + ";不写入日期=" + (CheckBox_DisableDate.IsChecked == true ? "1" : "0")
694 | + ";最大线程=" + TextBox_Max.Text
695 | + ";最小线程=" + TextBox_Min.Text
696 | + ";重试次数=" + TextBox_Retry.Text
697 | + ";超时秒数=" + TextBox_Timeout.Text
698 | + ";停止速度=" + TextBox_StopSpeed.Text
699 | + ";最大速度=" + TextBox_MaxSpeed.Text
700 | + ";不合并=" + (CheckBox_DisableMerge.IsChecked == true ? "1" : "0")
701 | + ";不使用系统代理=" + (CheckBox_DisableProxy.IsChecked == true ? "1" : "0")
702 | + ";仅合并音频=" + (CheckBox_AudioOnly.IsChecked == true ? "1" : "0");
703 | File.WriteAllText("config.txt", config);
704 | }
705 |
706 | private void Window_Loaded(object sender, RoutedEventArgs e)
707 | {
708 | Environment.CurrentDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
709 | //读取配置
710 | if (File.Exists("config.txt"))
711 | {
712 | string config = File.ReadAllText("config.txt");
713 |
714 | TextBox_EXE.Text = Encoding.UTF8.GetString(Convert.FromBase64String(FindCookie("程序路径", config)));
715 | TextBox_WorkDir.Text = Encoding.UTF8.GetString(Convert.FromBase64String(FindCookie("保存路径", config)));
716 | try
717 | {
718 | TextBox_Proxy.Text = Encoding.UTF8.GetString(Convert.FromBase64String(FindCookie("代理", config)));
719 | }
720 | catch (Exception) {; }
721 | try
722 | {
723 | TextBox_Headers.Text = Encoding.UTF8.GetString(Convert.FromBase64String(FindCookie("请求头", config)));
724 | }
725 | catch (Exception) {; }
726 | if (FindCookie("删除临时文件", config) == "1")
727 | CheckBox_Del.IsChecked = true;
728 | if (FindCookie("MP4混流边下边看", config) == "1")
729 | CheckBox_FastStart.IsChecked = true;
730 | if (FindCookie("二进制合并", config) == "1")
731 | CheckBox_BinaryMerge.IsChecked = true;
732 | if (FindCookie("仅解析模式", config) == "1")
733 | CheckBox_ParserOnly.IsChecked = true;
734 | if (FindCookie("不写入日期", config) == "1")
735 | CheckBox_DisableDate.IsChecked = true;
736 | TextBox_Max.Text = FindCookie("最大线程", config);
737 | TextBox_Min.Text = FindCookie("最小线程", config);
738 | TextBox_Retry.Text = FindCookie("重试次数", config);
739 | try
740 | {
741 | if (!string.IsNullOrEmpty(FindCookie("超时秒数", config)))
742 | TextBox_Timeout.Text = FindCookie("超时秒数", config);
743 | }
744 | catch (Exception) {; }
745 | try
746 | {
747 | if (!string.IsNullOrEmpty(FindCookie("停止速度", config)))
748 | TextBox_StopSpeed.Text = FindCookie("停止速度", config);
749 | }
750 | catch (Exception) {; }
751 | try
752 | {
753 | if (!string.IsNullOrEmpty(FindCookie("最大速度", config)))
754 | TextBox_MaxSpeed.Text = FindCookie("最大速度", config);
755 | }
756 | catch (Exception) {; }
757 | try
758 | {
759 | if (FindCookie("不合并", config) == "1")
760 | CheckBox_DisableMerge.IsChecked = true;
761 | if (FindCookie("不使用系统代理", config) == "1")
762 | CheckBox_DisableProxy.IsChecked = true;
763 | }
764 | catch (Exception) {; }
765 | try
766 | {
767 | if (FindCookie("仅合并音频", config) == "1")
768 | CheckBox_AudioOnly.IsChecked = true;
769 | }
770 | catch (Exception) {; }
771 | }
772 |
773 | if (!File.Exists(TextBox_EXE.Text))//尝试寻找主程序
774 | {
775 | DirectoryInfo d = new DirectoryInfo(Environment.CurrentDirectory);
776 | foreach (FileInfo fi in d.GetFiles().Reverse())
777 | {
778 | if (fi.Extension.ToUpper() == ".exe".ToUpper() && fi.Name.StartsWith("N_m3u8DL-CLI_"))
779 | {
780 | TextBox_EXE.Text = fi.Name;
781 | }
782 | }
783 | }
784 |
785 | if (Environment.GetCommandLineArgs().Length > 1)
786 | {
787 | var ext = Path.GetExtension(Environment.GetCommandLineArgs()[1]);
788 | if (ext == ".m3u8" || ext == ".json" || ext == ".txt" || Directory.Exists(Environment.GetCommandLineArgs()[1]))
789 | TextBox_URL.Text = Environment.GetCommandLineArgs()[1];
790 | if (TextBox_URL.Text != "")
791 | {
792 | FlashTextBox(TextBox_URL);
793 | if (!Directory.Exists(TextBox_URL.Text))
794 | TextBox_Title.Text = GetTitleFromURL(TextBox_URL.Text);
795 | }
796 | }
797 | else
798 | {
799 | //从剪切板读取url
800 | Regex url = new Regex(@"(https?)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]", RegexOptions.Compiled | RegexOptions.Singleline);
801 | string str = url.Match(Clipboard.GetText()).Value;
802 | TextBox_URL.Text = str;
803 | if (TextBox_URL.Text != "")
804 | {
805 | FlashTextBox(TextBox_URL);
806 | TextBox_Title.Text = GetTitleFromURL(TextBox_URL.Text);
807 | }
808 | }
809 | }
810 |
811 | private void Button_GO_Click(object sender, RoutedEventArgs e)
812 | {
813 | //hex to base64
814 | try
815 | {
816 | TextBox_Key.Text = Convert.ToBase64String(HexStringToBytes(TextBox_Key.Text));
817 | }
818 | catch(Exception) {
819 |
820 | }
821 | if (!File.Exists(TextBox_EXE.Text))
822 | {
823 | MessageBox.Show(Properties.Resources.String2);
824 | return;
825 | }
826 | if (TextBox_URL.Text == "")
827 | {
828 | MessageBox.Show(Properties.Resources.String3);
829 | return;
830 | }
831 | if (TextBox_Proxy.Text != "" && (!TextBox_Proxy.Text.StartsWith("http://") && !TextBox_Proxy.Text.StartsWith("socks5://")))
832 | {
833 | MessageBox.Show(Properties.Resources.String7);
834 | return;
835 | }
836 |
837 | //批量
838 | if ((!TextBox_URL.Text.StartsWith("http") && TextBox_URL.Text.EndsWith(".txt") && File.Exists(TextBox_URL.Text))
839 | || Directory.Exists(TextBox_URL.Text))
840 | {
841 | this.IsEnabled = false;
842 | Button_GO.Content = Properties.Resources.String4;
843 | string inputUrl = TextBox_URL.Text;
844 | string exePath = TextBox_EXE.Text;
845 | List m3u8list = new List();
846 | if (Directory.Exists(inputUrl))
847 | {
848 | foreach (var file in Directory.GetFiles(inputUrl))
849 | {
850 | if (new FileInfo(file).Name.ToLower().EndsWith(".m3u8") || new FileInfo(file).Name.ToLower().EndsWith(".mpd"))
851 | {
852 | m3u8list.Add(new FileInfo(file).FullName);
853 | }
854 | }
855 | StringBuilder sb = new StringBuilder();
856 | sb.AppendLine("@echo off");
857 | sb.AppendLine("::Created by N_m3u8DL-CLI-SimpleG\r\n");
858 | //sb.AppendLine("chcp 65001 >nul");
859 | int i = 0;
860 | foreach (var item in m3u8list)
861 | {
862 | TextBox_Title.Text = GetTitleFromURL(item);
863 | sb.AppendLine($"TITLE \"[{++i}/{m3u8list.Count}] - {TextBox_Title.Text}\"");
864 | sb.AppendLine("\"" + exePath + "\" \"" + item.Replace("%", "%%") + "\" " + TextBox_Parameter.Text.Remove(0, TextBox_Parameter.Text.IndexOf("\" ") + 2));
865 | }
866 | //sb.AppendLine("del %0");
867 | string bat = "Batch-" + DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss") + ".bat";
868 | File.WriteAllText(bat,
869 | sb.ToString(),
870 | Encoding.Default);
871 | Process.Start(bat);
872 | }
873 | else
874 | {
875 | m3u8list = File.ReadAllLines(inputUrl, GetType(inputUrl)).ToList();
876 | StringBuilder sb = new StringBuilder();
877 | sb.AppendLine("@echo off");
878 | sb.AppendLine("::Created by N_m3u8DL-CLI-SimpleG");
879 | //sb.AppendLine("chcp 65001 >nul");
880 | int i = 0;
881 | foreach (var item in m3u8list)
882 | {
883 | if (item.Trim() != "")
884 | {
885 | if (item.StartsWith("http"))
886 | {
887 | TextBox_Title.Text = GetTitleFromURL(item);
888 | sb.AppendLine($"TITLE \"[{++i}/{m3u8list.Count}] - {TextBox_Title.Text}\"");
889 | sb.AppendLine("\"" + exePath + "\" \"" + item.Replace("%", "%%") + "\" " + TextBox_Parameter.Text.Remove(0, TextBox_Parameter.Text.IndexOf("\" ") + 2));
890 | }
891 | //自定义文件名
892 | else
893 | {
894 | TextBox_Title.Text = item.Substring(0, item.IndexOf(",http"));
895 | sb.AppendLine($"TITLE \"[{++i}/{m3u8list.Count}] - {TextBox_Title.Text}\"");
896 | sb.AppendLine("\"" + exePath + "\" \"" + item.Replace(TextBox_Title.Text + ",", "").Replace("%", "%%") + "\" " + TextBox_Parameter.Text.Remove(0, TextBox_Parameter.Text.IndexOf("\" ") + 2));
897 | }
898 | }
899 | }
900 | //sb.AppendLine("del %0");
901 | string bat = "Batch-" + DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss") + ".bat";
902 | File.WriteAllText(bat,
903 | sb.ToString(),
904 | Encoding.Default);
905 | Process.Start(bat);
906 | }
907 |
908 | Button_GO.Content = "GO";
909 | this.IsEnabled = true;
910 | }
911 | else
912 | {
913 | Button_GO.IsEnabled = false;
914 | Process.Start(TextBox_EXE.Text, TextBox_Parameter.Text);
915 | Button_GO.IsEnabled = true;
916 | }
917 | }
918 |
919 | private void TextBox_URL_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
920 | {
921 | if (e.Key == Key.Enter)
922 | Button_GO.RaiseEvent(new RoutedEventArgs(System.Windows.Controls.Primitives.ButtonBase.ClickEvent));
923 | }
924 |
925 | private void TextBox_Title_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
926 | {
927 | if (e.Key == Key.Enter)
928 | Button_GO.RaiseEvent(new RoutedEventArgs(System.Windows.Controls.Primitives.ButtonBase.ClickEvent));
929 | }
930 |
931 | private void SetTopMost(object sender, RoutedEventArgs e)
932 | {
933 | if (CheckBox_TopMost.IsChecked == true)
934 | {
935 | Topmost = true;
936 | }
937 | else
938 | {
939 | Topmost = false;
940 | }
941 | }
942 |
943 | private void Menu_GetDownloader(object sender, RoutedEventArgs e)
944 | {
945 | Process.Start("https://github.com/nilaoda/N_m3u8DL-CLI/releases");
946 | }
947 |
948 | ///
949 | /// 给定文件的路径,读取文件的二进制数据,判断文件的编码类型
950 | ///
951 | /// 文件路径
952 | /// 文件的编码类型
953 | public static Encoding GetType(string FILE_NAME)
954 | {
955 | FileStream fs = new FileStream(FILE_NAME, FileMode.Open, FileAccess.Read);
956 | Encoding r = GetType(fs);
957 | fs.Close();
958 | return r;
959 | }
960 |
961 | ///
962 | /// 通过给定的文件流,判断文件的编码类型
963 | ///
964 | /// 文件流
965 | /// 文件的编码类型
966 | public static Encoding GetType(FileStream fs)
967 | {
968 | byte[] Unicode = new byte[] { 0xFF, 0xFE, 0x41 };
969 | byte[] UnicodeBIG = new byte[] { 0xFE, 0xFF, 0x00 };
970 | byte[] UTF8 = new byte[] { 0xEF, 0xBB, 0xBF }; //带BOM
971 | Encoding reVal = Encoding.Default;
972 |
973 | BinaryReader r = new BinaryReader(fs, System.Text.Encoding.Default);
974 | int i;
975 | int.TryParse(fs.Length.ToString(), out i);
976 | byte[] ss = r.ReadBytes(i);
977 | if (IsUTF8Bytes(ss) || (ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF))
978 | {
979 | reVal = Encoding.UTF8;
980 | }
981 | else if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00)
982 | {
983 | reVal = Encoding.BigEndianUnicode;
984 | }
985 | else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41)
986 | {
987 | reVal = Encoding.Unicode;
988 | }
989 | r.Close();
990 | return reVal;
991 | }
992 |
993 | ///
994 | /// 判断是否是不带 BOM 的 UTF8 格式
995 | ///
996 | ///
997 | ///
998 | private static bool IsUTF8Bytes(byte[] data)
999 | {
1000 | int charByteCounter = 1; //计算当前正分析的字符应还有的字节数
1001 | byte curByte; //当前分析的字节.
1002 | for (int i = 0; i < data.Length; i++)
1003 | {
1004 | curByte = data[i];
1005 | if (charByteCounter == 1)
1006 | {
1007 | if (curByte >= 0x80)
1008 | {
1009 | //判断当前
1010 | while (((curByte <<= 1) & 0x80) != 0)
1011 | {
1012 | charByteCounter++;
1013 | }
1014 | //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X
1015 | if (charByteCounter == 1 || charByteCounter > 6)
1016 | {
1017 | return false;
1018 | }
1019 | }
1020 | }
1021 | else
1022 | {
1023 | //若是UTF-8 此时第一位必须为1
1024 | if ((curByte & 0xC0) != 0x80)
1025 | {
1026 | return false;
1027 | }
1028 | charByteCounter--;
1029 | }
1030 | }
1031 | if (charByteCounter > 1)
1032 | {
1033 | throw new Exception(Properties.Resources.String5);
1034 | }
1035 | return true;
1036 | }
1037 |
1038 | private void TextBox_Key_PreviewDragEnter(object sender, System.Windows.DragEventArgs e)
1039 | {
1040 | e.Effects = DragDropEffects.Copy;
1041 | e.Handled = true;
1042 | }
1043 |
1044 | private void TextBox_Key_PreviewDragOver(object sender, System.Windows.DragEventArgs e)
1045 | {
1046 | e.Effects = DragDropEffects.Copy;
1047 | e.Handled = true;
1048 | }
1049 |
1050 | private void TextBox_Key_PreviewDrop(object sender, System.Windows.DragEventArgs e)
1051 | {
1052 | if (e.Data.GetDataPresent(DataFormats.FileDrop, false) == true)
1053 | {
1054 | //获取拖拽的文件地址
1055 | string path = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
1056 | e.Effects = DragDropEffects.Copy;
1057 | e.Handled = true;
1058 | if (new FileInfo(path).Length == 16)
1059 | TextBox_Key.Text = path; //将获取到的完整路径赋值到textBox1
1060 | else
1061 | MessageBox.Show(Properties.Resources.String6);
1062 | }
1063 | }
1064 | }
1065 | }
1066 |
--------------------------------------------------------------------------------