You've already forked N_m3u8DL-CLI
							
							
				mirror of
				https://github.com/nilaoda/N_m3u8DL-CLI
				synced 2025-10-31 18:00:51 +01:00 
			
		
		
		
	Compare commits
	
		
			334 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | f5a9ed08a1 | ||
|   | 6b8bfde19f | ||
|   | ff738f2849 | ||
|   | 3d35c24a2e | ||
|   | 41d7151e7e | ||
|   | 94246ef163 | ||
|   | 9c118631cf | ||
|   | 2ee9ab234f | ||
|   | 606f2184df | ||
|   | 7dd2b6cee2 | ||
|   | f744aa990e | ||
|   | 97c9f444b8 | ||
|   | 8aac37bbe2 | ||
|   | b7e19ec699 | ||
|   | 7e7c5c6ba9 | ||
|   | 50722079ba | ||
|   | d529ece032 | ||
|   | 9ed8b359a1 | ||
|   | a7591e3978 | ||
|   | 094a89bc79 | ||
|   | 9e7b603d3b | ||
|   | 3801090928 | ||
|   | 42c1d628d4 | ||
|   | ecefecd827 | ||
|   | 4661818c1f | ||
|   | fa61cd136d | ||
|   | 472fb0cf02 | ||
|   | 28e39a94ac | ||
|   | a42ade64f3 | ||
|   | 539f773e37 | ||
|   | d6f27cf90f | ||
|   | 8912ee5e4b | ||
|   | 409437b2c7 | ||
|   | 350d3b508d | ||
|   | 1e3f06eaae | ||
|   | 2d4bc42d55 | ||
|   | 68e06d3fa7 | ||
|   | 6c3340e94e | ||
|   | 051faa9f2b | ||
|   | 115f9c9424 | ||
|   | faf67cd527 | ||
|   | 38d1a1a2dc | ||
|   | 12eb68d592 | ||
|   | 0804e295e5 | ||
|   | 847c4683cb | ||
|   | 8c72947860 | ||
|   | f0b240a6ee | ||
|   | 793cf53042 | ||
|   | 612fc29197 | ||
|   | 307e2389de | ||
|   | 1c932abdc3 | ||
|   | 314f0065c7 | ||
|   | 59060bb74d | ||
|   | cab882c3a3 | ||
|   | 9955532ce5 | ||
|   | 7e127be8c2 | ||
|   | b46571a57f | ||
|   | da5861d907 | ||
|   | 92bc91a1fb | ||
|   | 439f50103e | ||
|   | 8a95e31b2f | ||
|   | 115b8a156a | ||
|   | 120bcaebb5 | ||
|   | 455d56707c | ||
|   | 048adcf118 | ||
|   | fe5aa27b1c | ||
|   | 039aa489b1 | ||
|   | 14e80f0b06 | ||
|   | 2256fff549 | ||
|   | 84cfd4e138 | ||
|   | e70c229135 | ||
|   | 8b520d0c19 | ||
|   | 71d69de51a | ||
|   | bc89ead00d | ||
|   | ae79d6eb3a | ||
|   | 96bd8af883 | ||
|   | 89b1e30e0f | ||
|   | 7a741359ab | ||
|   | 564b6ad291 | ||
|   | a0fc9404f7 | ||
|   | 5267be1699 | ||
|   | 20bfda39e7 | ||
|   | ba4c0eeda7 | ||
|   | 5d72e24002 | ||
|   | a87c051d23 | ||
|   | 44e1b68d6b | ||
|   | e65dfa52cd | ||
|   | 965c173899 | ||
|   | 880af02cc2 | ||
|   | 2742de43c4 | ||
|   | 9d8cb57390 | ||
|   | 9e2a192dab | ||
|   | 33cf9e2256 | ||
|   | 2959cbbb5c | ||
|   | c2eb8a6adc | ||
|   | e1b591b81c | ||
|   | 334b1939b5 | ||
|   | 7e916b65fd | ||
|   | 4ead563fa2 | ||
|   | 1b387a06e5 | ||
|   | 6e7b4ac7ea | ||
|   | e98c5205d1 | ||
|   | d7890dd124 | ||
|   | 82f2111522 | ||
|   | 4c3207586f | ||
|   | 69b411e37c | ||
|   | 1e8525041f | ||
|   | 65ae72d4a4 | ||
|   | 4a4bfae5ab | ||
|   | d586dddfcd | ||
|   | fca6b3ff6c | ||
|   | 5d75626a36 | ||
|   | a94271c244 | ||
|   | c51118dce7 | ||
|   | 81b2e87bf7 | ||
|   | 71a9878aaa | ||
|   | 769fe4e926 | ||
|   | 1f57ba7c09 | ||
|   | 71282bda30 | ||
|   | 41ee8aebdf | ||
|   | a4537bc093 | ||
|   | b8a60b3917 | ||
|   | 8091dd290f | ||
|   | d48e84e611 | ||
|   | 9f5423a437 | ||
|   | ce7e38770a | ||
|   | 8fdb2e918e | ||
|   | d4b7d240c1 | ||
|   | 484d2941ed | ||
|   | a0f2b66575 | ||
|   | 65cc0681e2 | ||
|   | 7d980ec9a2 | ||
|   | ec5892c05a | ||
|   | 9aed50fbf9 | ||
|   | d657b455cd | ||
|   | cda6575605 | ||
|   | 0d6377d41b | ||
|   | 9c76bdcbce | ||
|   | 83915ff606 | ||
|   | 9cd4746f33 | ||
|   | 33a5b917ac | ||
|   | f69978bd82 | ||
|   | d9fd526886 | ||
|   | 1cc8ecfaaf | ||
|   | 2bc2dde2ad | ||
|   | c3ddcf9e0e | ||
|   | ba5d20dd02 | ||
|   | 16f705fe66 | ||
|   | d141cabc4a | ||
|   | adcf884a93 | ||
|   | 9d903a025f | ||
|   | 0bd23ab641 | ||
|   | a38f27ccd7 | ||
|   | 3acec5efd3 | ||
|   | 90874e4bfe | ||
|   | b94768e3e8 | ||
|   | 311f3b882e | ||
|   | 4b4f537984 | ||
|   | 8032d50b42 | ||
|   | f615764e55 | ||
|   | ccaa200ef8 | ||
|   | 6058d878eb | ||
|   | c712c6dee0 | ||
|   | bb24bb998f | ||
|   | e9d951efa5 | ||
|   | 6f88a805ef | ||
|   | 6aa6d63a8d | ||
|   | 147246caba | ||
|   | 35c1ee4777 | ||
|   | 8b32081b85 | ||
|   | c00de328d1 | ||
|   | d5193c1645 | ||
|   | c06fbf5820 | ||
|   | e700edba56 | ||
|   | aad948da7c | ||
|   | 14f7b20176 | ||
|   | a66a9a4096 | ||
|   | c862f23a9c | ||
|   | 1a722e80de | ||
|   | eff43e8ac3 | ||
|   | 7648f8f8dc | ||
|   | 1edc1a43fe | ||
|   | 01e7735018 | ||
|   | a0c41d6116 | ||
|   | c3c25774de | ||
|   | ba40641a21 | ||
|   | 5d76418780 | ||
|   | fd48b766b5 | ||
|   | 0f25cc0ae8 | ||
|   | 1c6bd688e3 | ||
|   | 480857cc3b | ||
|   | 52af9a44a8 | ||
|   | 84d137b504 | ||
|   | a4f1064c81 | ||
|   | eac08b12f8 | ||
|   | c81c911888 | ||
|   | 361e901e5b | ||
|   | 3567f4c4cc | ||
|   | 2f7b0f7304 | ||
|   | 000d0db4ae | ||
|   | d551ad52c1 | ||
|   | c064c83c21 | ||
|   | f6ed0f9e4d | ||
|   | f65fee94ca | ||
|   | ce64a92b0d | ||
|   | 42790ce540 | ||
|   | 83d8ca1c8c | ||
|   | 4b5a64eb98 | ||
|   | 2b5af09c3b | ||
|   | 6368adc2ab | ||
|   | fcd7840091 | ||
|   | d77cb62dff | ||
|   | 34394c6a2b | ||
|   | 091cba8555 | ||
|   | b02b6b7168 | ||
|   | b7408b0599 | ||
|   | b83cb35170 | ||
|   | ed0a7b71a7 | ||
|   | 50eae19bf3 | ||
|   | cba8f3ea52 | ||
|   | 7fd93e1232 | ||
|   | 74a7e3c3ec | ||
|   | 849d712e11 | ||
|   | 7544f3a02c | ||
|   | 0120736c53 | ||
|   | e4bde4926c | ||
|   | d42cd6a60d | ||
|   | 175f13adc9 | ||
|   | 72f1c043b1 | ||
|   | a2e2070f5d | ||
|   | 6c96deb366 | ||
|   | 2bd900ee5d | ||
|   | 1261810510 | ||
|   | 26823dbd7e | ||
|   | 698699d9fc | ||
|   | ebed7fa1e3 | ||
|   | 73a8348155 | ||
|   | 5ace0b3a4f | ||
|   | 5abe889da0 | ||
|   | f1070fd1b4 | ||
|   | 4af82cc7f9 | ||
|   | 809380b7ab | ||
|   | ab57420507 | ||
|   | 80230f12fe | ||
|   | a6c7c0fd8c | ||
|   | bd6df6b58c | ||
|   | e0a9071d62 | ||
|   | 5c9bcf72d2 | ||
|   | 7cf2c12d0c | ||
|   | 1b35fe2d2c | ||
|   | ed3aae1cb9 | ||
|   | 01c2ecbeb5 | ||
|   | 9993ec8177 | ||
|   | 464300c860 | ||
|   | 45fa58a46f | ||
|   | f93ddc7107 | ||
|   | 05f450fa6d | ||
|   | 580c374d7b | ||
|   | b58dc5d8e0 | ||
|   | f50cf7862a | ||
|   | fdad68d483 | ||
|   | d7aaa5323b | ||
|   | 6c2e13b800 | ||
|   | 086fc57958 | ||
|   | bc349b8977 | ||
|   | cc4efed3c6 | ||
|   | cf958e833b | ||
|   | fb09add0cd | ||
|   | 5a3c5baefd | ||
|   | 839afd8e61 | ||
|   | 338c7a25d0 | ||
|   | f57ce8c2da | ||
|   | a5009e1683 | ||
|   | 66933da9de | ||
|   | 136389e248 | ||
|   | 7971104bd4 | ||
|   | cc4941554d | ||
|   | c50371080a | ||
|   | 154c5f84a1 | ||
|   | 1556ee42df | ||
|   | 121ff9f226 | ||
|   | e5b84c2f04 | ||
|   | 7e562a06bb | ||
|   | 1eae19c3ea | ||
|   | ba33049b99 | ||
|   | 9773087bf9 | ||
|   | b60d39ad0d | ||
|   | e89705a370 | ||
|   | 4aea16d672 | ||
|   | afc69eae1a | ||
|   | 2446a25b35 | ||
|   | d37524180d | ||
|   | b02a29fbb7 | ||
|   | e87d02230d | ||
|   | 63609a0970 | ||
|   | 1fe798ab19 | ||
|   | 21b9977501 | ||
|   | fbe37be499 | ||
|   | 6416dd642d | ||
|   | 967f0582a6 | ||
|   | a5aeffc6ec | ||
|   | 745cbd92ad | ||
|   | 4a4412a262 | ||
|   | 084989b3ce | ||
|   | 640208d95c | ||
|   | ad148ba4c7 | ||
|   | 7c961dbbbf | ||
|   | 83df7b4301 | ||
|   | 860282a463 | ||
|   | 70582029dd | ||
|   | 1f3002ef66 | ||
|   | 07c758dd00 | ||
|   | 38f2f5589f | ||
|   | c7b9414613 | ||
|   | 84953fa16a | ||
|   | 4cf88711d6 | ||
|   | b59940f719 | ||
|   | 6a6a338868 | ||
|   | 0d74380e1c | ||
|   | 5a398bdb79 | ||
|   | c2953a3d43 | ||
|   | 6f2ebfba2d | ||
|   | 3c1b893919 | ||
|   | 8b6f411af9 | ||
|   | 6cfd74f3a0 | ||
|   | 044068016b | ||
|   | 6d21ef0a10 | ||
|   | 6d1834ca9f | ||
|   | 3e215359b4 | ||
|   | 3d9610d3bb | ||
|   | 377c575c72 | ||
|   | c02d737125 | ||
|   | c1fb395ee0 | ||
|   | 3920ae6178 | 
							
								
								
									
										63
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | ############################################################################### | ||||||
|  | # Set default behavior to automatically normalize line endings. | ||||||
|  | ############################################################################### | ||||||
|  | * text=auto | ||||||
|  |  | ||||||
|  | ############################################################################### | ||||||
|  | # Set default behavior for command prompt diff. | ||||||
|  | # | ||||||
|  | # This is need for earlier builds of msysgit that does not have it on by | ||||||
|  | # default for csharp files. | ||||||
|  | # Note: This is only used by command line | ||||||
|  | ############################################################################### | ||||||
|  | #*.cs     diff=csharp | ||||||
|  |  | ||||||
|  | ############################################################################### | ||||||
|  | # Set the merge driver for project and solution files | ||||||
|  | # | ||||||
|  | # Merging from the command prompt will add diff markers to the files if there | ||||||
|  | # are conflicts (Merging from VS is not affected by the settings below, in VS | ||||||
|  | # the diff markers are never inserted). Diff markers may cause the following  | ||||||
|  | # file extensions to fail to load in VS. An alternative would be to treat | ||||||
|  | # these files as binary and thus will always conflict and require user | ||||||
|  | # intervention with every merge. To do so, just uncomment the entries below | ||||||
|  | ############################################################################### | ||||||
|  | #*.sln       merge=binary | ||||||
|  | #*.csproj    merge=binary | ||||||
|  | #*.vbproj    merge=binary | ||||||
|  | #*.vcxproj   merge=binary | ||||||
|  | #*.vcproj    merge=binary | ||||||
|  | #*.dbproj    merge=binary | ||||||
|  | #*.fsproj    merge=binary | ||||||
|  | #*.lsproj    merge=binary | ||||||
|  | #*.wixproj   merge=binary | ||||||
|  | #*.modelproj merge=binary | ||||||
|  | #*.sqlproj   merge=binary | ||||||
|  | #*.wwaproj   merge=binary | ||||||
|  |  | ||||||
|  | ############################################################################### | ||||||
|  | # behavior for image files | ||||||
|  | # | ||||||
|  | # image files are treated as binary by default. | ||||||
|  | ############################################################################### | ||||||
|  | #*.jpg   binary | ||||||
|  | #*.png   binary | ||||||
|  | #*.gif   binary | ||||||
|  |  | ||||||
|  | ############################################################################### | ||||||
|  | # diff behavior for common document formats | ||||||
|  | #  | ||||||
|  | # Convert binary document formats to text before diffing them. This feature | ||||||
|  | # is only available from the command line. Turn it on by uncommenting the  | ||||||
|  | # entries below. | ||||||
|  | ############################################################################### | ||||||
|  | #*.doc   diff=astextplain | ||||||
|  | #*.DOC   diff=astextplain | ||||||
|  | #*.docx  diff=astextplain | ||||||
|  | #*.DOCX  diff=astextplain | ||||||
|  | #*.dot   diff=astextplain | ||||||
|  | #*.DOT   diff=astextplain | ||||||
|  | #*.pdf   diff=astextplain | ||||||
|  | #*.PDF   diff=astextplain | ||||||
|  | #*.rtf   diff=astextplain | ||||||
|  | #*.RTF   diff=astextplain | ||||||
							
								
								
									
										34
									
								
								.github/workflows/build_latest.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								.github/workflows/build_latest.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | name: Build_Latest | ||||||
|  |   | ||||||
|  | on: [push] | ||||||
|  |   | ||||||
|  | jobs: | ||||||
|  |   build: | ||||||
|  |   | ||||||
|  |     runs-on: windows-latest | ||||||
|  |   | ||||||
|  |     steps: | ||||||
|  |     - uses: actions/checkout@v1 | ||||||
|  |       name: Checkout Code | ||||||
|  |       | ||||||
|  |     - name: Setup MSBuild Path | ||||||
|  |       uses: warrenbuckley/Setup-MSBuild@v1 | ||||||
|  |       env: | ||||||
|  |         ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' | ||||||
|  |         | ||||||
|  |     - name: Setup NuGet | ||||||
|  |       uses: NuGet/setup-nuget@v1.0.2 | ||||||
|  |       env: | ||||||
|  |         ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true' | ||||||
|  |       | ||||||
|  |     - name: Restore NuGet Packages | ||||||
|  |       run: nuget restore N_m3u8DL-CLI.sln | ||||||
|  |   | ||||||
|  |     - name: Build  | ||||||
|  |       run: msbuild N_m3u8DL-CLI.sln /p:Configuration=Release /p:DebugSymbols=false /p:DebugType=None | ||||||
|  |   | ||||||
|  |     - name: Upload Artifact | ||||||
|  |       uses: actions/upload-artifact@v1.0.0 | ||||||
|  |       with: | ||||||
|  |         name: N_m3u8DL-CLI_latest | ||||||
|  |         path: N_m3u8DL-CLI\bin\Release\N_m3u8DL-CLI.exe | ||||||
							
								
								
									
										261
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | MIT License | ||||||
|  |  | ||||||
|  | Copyright (c) 2019 nilaoda | ||||||
|  |  | ||||||
|  | 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. | ||||||
							
								
								
									
										25
									
								
								N_m3u8DL-CLI.sln
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								N_m3u8DL-CLI.sln
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  |  | ||||||
|  | Microsoft Visual Studio Solution File, Format Version 12.00 | ||||||
|  | # Visual Studio Version 16 | ||||||
|  | VisualStudioVersion = 16.0.29215.179 | ||||||
|  | MinimumVisualStudioVersion = 10.0.40219.1 | ||||||
|  | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "N_m3u8DL-CLI", "N_m3u8DL-CLI\N_m3u8DL-CLI.csproj", "{4FB61439-B738-46AC-B3AF-2BF72150D057}" | ||||||
|  | EndProject | ||||||
|  | Global | ||||||
|  | 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||||
|  | 		Debug|Any CPU = Debug|Any CPU | ||||||
|  | 		Release|Any CPU = Release|Any CPU | ||||||
|  | 	EndGlobalSection | ||||||
|  | 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||||
|  | 		{4FB61439-B738-46AC-B3AF-2BF72150D057}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||||
|  | 		{4FB61439-B738-46AC-B3AF-2BF72150D057}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||||
|  | 		{4FB61439-B738-46AC-B3AF-2BF72150D057}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||||
|  | 		{4FB61439-B738-46AC-B3AF-2BF72150D057}.Release|Any CPU.Build.0 = Release|Any CPU | ||||||
|  | 	EndGlobalSection | ||||||
|  | 	GlobalSection(SolutionProperties) = preSolution | ||||||
|  | 		HideSolutionNode = FALSE | ||||||
|  | 	EndGlobalSection | ||||||
|  | 	GlobalSection(ExtensibilityGlobals) = postSolution | ||||||
|  | 		SolutionGuid = {82B9270D-B7B2-4591-BF8A-5B4EBCD0EA8A} | ||||||
|  | 	EndGlobalSection | ||||||
|  | EndGlobal | ||||||
							
								
								
									
										6
									
								
								N_m3u8DL-CLI/App.config
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								N_m3u8DL-CLI/App.config
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <configuration> | ||||||
|  |     <startup>  | ||||||
|  |          | ||||||
|  |     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/></startup> | ||||||
|  | </configuration> | ||||||
							
								
								
									
										661
									
								
								N_m3u8DL-CLI/CSChaCha20.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										661
									
								
								N_m3u8DL-CLI/CSChaCha20.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										318
									
								
								N_m3u8DL-CLI/Decode51CtoKey.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										318
									
								
								N_m3u8DL-CLI/Decode51CtoKey.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										83
									
								
								N_m3u8DL-CLI/DecodeCdeledu.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								N_m3u8DL-CLI/DecodeCdeledu.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | |||||||
|  | using NiL.JS.BaseLibrary; | ||||||
|  | using NiL.JS.Core; | ||||||
|  | using NiL.JS.Extensions; | ||||||
|  | using System; | ||||||
|  | using Array = System.Array; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     internal class DecodeCdeledu | ||||||
|  |     { | ||||||
|  |         private static string JS = @" | ||||||
|  | var _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; | ||||||
|  |  | ||||||
|  | var removePaddingChars = function(input) { | ||||||
|  |     var lkey = _keyStr.indexOf(input.charAt(input.length - 1)); | ||||||
|  |     if (lkey == 64) { | ||||||
|  |         return input.substring(0, input.length - 1); | ||||||
|  |     } | ||||||
|  |     return input; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var base64Decode = function(input, arrayBuffer) { | ||||||
|  |     input = removePaddingChars(input); | ||||||
|  |     input = removePaddingChars(input); | ||||||
|  |     var bytes = parseInt((input.length / 4) * 3, 10); | ||||||
|  |     var uarray; | ||||||
|  |     var chr1, chr2, chr3; | ||||||
|  |     var enc1, enc2, enc3, enc4; | ||||||
|  |     var i = 0; | ||||||
|  |     var j = 0; | ||||||
|  |     if (arrayBuffer) { | ||||||
|  |         uarray = new Uint8Array(arrayBuffer); | ||||||
|  |     } else { | ||||||
|  |         uarray = new Uint8Array(bytes); | ||||||
|  |     } | ||||||
|  |     input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ''); | ||||||
|  |     for (i = 0; i < bytes; i += 3) { | ||||||
|  |         enc1 = _keyStr.indexOf(input.charAt(j++)); | ||||||
|  |         enc2 = _keyStr.indexOf(input.charAt(j++)); | ||||||
|  |         enc3 = _keyStr.indexOf(input.charAt(j++)); | ||||||
|  |         enc4 = _keyStr.indexOf(input.charAt(j++)); | ||||||
|  |         chr1 = (enc1 << 2) | (enc2 >> 4); | ||||||
|  |         chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); | ||||||
|  |         chr3 = ((enc3 & 3) << 6) | enc4; | ||||||
|  |         uarray[i] = chr1; | ||||||
|  |         if (enc3 != 64) | ||||||
|  |             uarray[i + 1] = chr2; | ||||||
|  |         if (enc4 != 64) | ||||||
|  |             uarray[i + 2] = chr3; | ||||||
|  |     } | ||||||
|  |     return uarray; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var uint8ArrayToString = function(uDataArr) { | ||||||
|  |     var arrStr = ''; | ||||||
|  |     for (var i = 0; i < uDataArr.length; i++) { | ||||||
|  |         arrStr += String.fromCharCode(uDataArr[i]); | ||||||
|  |     } | ||||||
|  |     return arrStr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var decodeKey = function(dataKeyString) { | ||||||
|  |     var decodeArr = base64Decode(dataKeyString); | ||||||
|  |     var decodeArrString = uint8ArrayToString(decodeArr); | ||||||
|  |     return decodeArrString; | ||||||
|  |     if (decodeArrString.indexOf('|&|') > 0) { | ||||||
|  |         return decodeArrString; | ||||||
|  |     } | ||||||
|  |     return ''; | ||||||
|  | } | ||||||
|  | "; | ||||||
|  |         //https://video.cdeledu.com/js/lib/cdel.hls.min-1.0.js?v=1.3 | ||||||
|  |         public static string DecodeKey(string txt) | ||||||
|  |         { | ||||||
|  |             var context = new Context(); | ||||||
|  |             context.Eval(JS); | ||||||
|  |             var concatFunction = context.GetVariable("decodeKey").As<Function>(); | ||||||
|  |             string key = concatFunction.Call(new Arguments { txt }).ToString(); | ||||||
|  |             string realKey = key.Split(new string[] { "|&|" }, StringSplitOptions.None)[1]; | ||||||
|  |             return realKey; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										41
									
								
								N_m3u8DL-CLI/DecodeDdyun.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								N_m3u8DL-CLI/DecodeDdyun.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | using System.Security.Cryptography; | ||||||
|  | using System.Text; | ||||||
|  | using System.Text.RegularExpressions; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     class DecodeDdyun | ||||||
|  |     { | ||||||
|  |         public static string DecryptM3u8(byte[] byteArray) | ||||||
|  |         { | ||||||
|  |             string tmp = DecodeNfmovies.DecryptM3u8(byteArray); | ||||||
|  |             if (tmp.StartsWith("duoduo.key")) | ||||||
|  |             { | ||||||
|  |                 tmp = Regex.Replace(tmp, @"#EXT-X-BYTERANGE:.*\s", ""); | ||||||
|  |                 tmp = tmp.Replace("https:", "jump/https:") | ||||||
|  |                     .Replace("inews.gtimg.com", "puui.qpic.cn"); | ||||||
|  |             } | ||||||
|  |             return tmp; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         //https://player.ddyunp.com/jQuery.min.js?v1.5 | ||||||
|  |         public static string GetVaildM3u8Url(string url) | ||||||
|  |         { | ||||||
|  |             //url: https://hls.ddyunp.com/ddyun/id/1/key/playlist.m3u8 | ||||||
|  |             string id = Regex.Match(url, @"\w{20,}").Value; | ||||||
|  |             string tm = Global.GetTimeStamp(false); | ||||||
|  |             string t = ((long.Parse(tm) / 0x186a0) * 0x64).ToString(); | ||||||
|  |             string tmp = id + "duoduo" + "1" + t; | ||||||
|  |             MD5 md5 = MD5.Create(); | ||||||
|  |             byte[] bs = Encoding.UTF8.GetBytes(tmp); | ||||||
|  |             byte[] hs = md5.ComputeHash(bs); | ||||||
|  |             StringBuilder sb = new StringBuilder(); | ||||||
|  |             foreach (byte b in hs) | ||||||
|  |             { | ||||||
|  |                 sb.Append(b.ToString("x2")); | ||||||
|  |             } | ||||||
|  |             string key = sb.ToString(); | ||||||
|  |             return Regex.Replace(url, @"1/\w{20,}", "1/" + key); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								N_m3u8DL-CLI/DecodeHuke88Key.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								N_m3u8DL-CLI/DecodeHuke88Key.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | using Newtonsoft.Json.Linq; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Security.Cryptography; | ||||||
|  | using System.Text; | ||||||
|  | using System.Text.RegularExpressions; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     //https://js.huke88.com/assets/revision/js/plugins/tcplayer/tcplayer.v4.1.min.js?v=930 | ||||||
|  |     //https://js.huke88.com/assets/revision/js/plugins/tcplayer/libs/hls.min.0.13.2m.js?v=930 | ||||||
|  |     class DecodeHuke88Key | ||||||
|  |     { | ||||||
|  |         private static string[] GetOverlayInfo(string url) | ||||||
|  |         { | ||||||
|  |             var enc = new Regex("eyJ\\w{100,}").Match(url).Value; | ||||||
|  |             var json = Encoding.UTF8.GetString(Convert.FromBase64String(enc)); | ||||||
|  |             JObject jObject = JObject.Parse(json); | ||||||
|  |             var key = jObject["overlayKey"].ToString(); | ||||||
|  |             var iv = jObject["overlayIv"].ToString(); | ||||||
|  |             return new string[] { key, iv }; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static string DecodeKey(string url, byte[] data) | ||||||
|  |         { | ||||||
|  |             var info = GetOverlayInfo(url); | ||||||
|  |             var overlayKey = info[0]; | ||||||
|  |             var overlayIv = info[1]; | ||||||
|  |             var l = new List<byte>(); | ||||||
|  |             var c = new List<byte>(); | ||||||
|  |             for (int h = 0; h < 16; h++) | ||||||
|  |             { | ||||||
|  |                 var f = overlayKey.Substring(2 * h, 2); | ||||||
|  |                 var g = overlayIv.Substring(2 * h, 2); | ||||||
|  |                 l.Add(Convert.ToByte(f, 16)); | ||||||
|  |                 c.Add(Convert.ToByte(g, 16)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var _lastCipherblock = c.ToArray(); | ||||||
|  |  | ||||||
|  |             var t = new byte[data.Length]; | ||||||
|  |             var r = data; | ||||||
|  |             r = Decrypter.AES128Decrypt(data, l.ToArray(), Decrypter.HexStringToBytes("00000000000000000000000000000000"), CipherMode.CBC, PaddingMode.Zeros); | ||||||
|  |  | ||||||
|  |             for (var o = 0; o < 16; o++) | ||||||
|  |                 t[o] = (byte)(r[o] ^ _lastCipherblock[o]); | ||||||
|  |  | ||||||
|  |             var key = Convert.ToBase64String(t); | ||||||
|  |  | ||||||
|  |             return key; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										203
									
								
								N_m3u8DL-CLI/DecodeImooc.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								N_m3u8DL-CLI/DecodeImooc.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | |||||||
|  | using NiL.JS.BaseLibrary; | ||||||
|  | using NiL.JS.Core; | ||||||
|  | using NiL.JS.Extensions; | ||||||
|  | using System; | ||||||
|  | using Array = System.Array; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     /* | ||||||
|  |      * js代码来自:https://www.imooc.com/static/moco/player/3.0.6.3/mocoplayer.js?v=202006122046 | ||||||
|  |      *  | ||||||
|  |      */ | ||||||
|  |     class DecodeImooc | ||||||
|  |     { | ||||||
|  |         private static string JS = @" | ||||||
|  | function n(t, e) { | ||||||
|  |                 function r(t, e) { | ||||||
|  |                     var r = ''; | ||||||
|  |                     if ('object' == typeof t) | ||||||
|  |                         for (var n = 0; n < t.length; n++) | ||||||
|  |                             r += String.fromCharCode(t[n]); | ||||||
|  |                     t = r || t; | ||||||
|  |                     for (var i, o, a = new Uint8Array(t.length), s = e.length, n = 0; n < t.length; n++) | ||||||
|  |                         o = n % s, | ||||||
|  |                         i = t[n], | ||||||
|  |                         i = i.toString().charCodeAt(0), | ||||||
|  |                         a[n] = i ^ e.charCodeAt(o); | ||||||
|  |                     return a | ||||||
|  |                 } | ||||||
|  |                 function n(t) { | ||||||
|  |                     var e = ''; | ||||||
|  |                     if ('object' == typeof t) | ||||||
|  |                         for (var r = 0; r < t.length; r++) | ||||||
|  |                             e += String.fromCharCode(t[r]); | ||||||
|  |                     t = e || t; | ||||||
|  |                     var n = new Uint8Array(t.length); | ||||||
|  |                     for (r = 0; r < t.length; r++) | ||||||
|  |                         n[r] = t[r].toString().charCodeAt(0); | ||||||
|  |                     var i, o, r = 0; | ||||||
|  |                     for (r = 0; r < n.length; r++) | ||||||
|  |                         0 != (i = n[r] % 3) && r + i < n.length && (o = n[r + 1], | ||||||
|  |                         n[r + 1] = n[r + i], | ||||||
|  |                         n[r + i] = o, | ||||||
|  |                         r = r + i + 1); | ||||||
|  |                     return n | ||||||
|  |                 } | ||||||
|  |                 function i(t) { | ||||||
|  |                     var e = ''; | ||||||
|  |                     if ('object' == typeof t) | ||||||
|  |                         for (var r = 0; r < t.length; r++) | ||||||
|  |                             e += String.fromCharCode(t[r]); | ||||||
|  |                     t = e || t; | ||||||
|  |                     var n = new Uint8Array(t.length); | ||||||
|  |                     for (r = 0; r < t.length; r++) | ||||||
|  |                         n[r] = t[r].toString().charCodeAt(0); | ||||||
|  |                     var r = 0 | ||||||
|  |                       , i = 0 | ||||||
|  |                       , o = 0 | ||||||
|  |                       , a = 0; | ||||||
|  |                     for (r = 0; r < n.length; r++) | ||||||
|  |                         o = n[r] % 2, | ||||||
|  |                         o && r++, | ||||||
|  |                         a++; | ||||||
|  |                     var s = new Uint8Array(a); | ||||||
|  |                     for (r = 0; r < n.length; r++) | ||||||
|  |                         o = n[r] % 2, | ||||||
|  |                         s[i++] = o ? n[r++] : n[r]; | ||||||
|  |                     return s | ||||||
|  |                 } | ||||||
|  |                 function o(t, e) { | ||||||
|  |                     var r = 0 | ||||||
|  |                       , n = 0 | ||||||
|  |                       , i = 0 | ||||||
|  |                       , o = 0 | ||||||
|  |                       , a = ''; | ||||||
|  |                     if ('object' == typeof t) | ||||||
|  |                         for (var r = 0; r < t.length; r++) | ||||||
|  |                             a += String.fromCharCode(t[r]); | ||||||
|  |                     t = a || t; | ||||||
|  |                     var s = new Uint8Array(t.length); | ||||||
|  |                     for (r = 0; r < t.length; r++) | ||||||
|  |                         s[r] = t[r].toString().charCodeAt(0); | ||||||
|  |                     for (r = 0; r < t.length; r++) | ||||||
|  |                         if (0 != (o = s[r] % 5) && 1 != o && r + o < s.length && (i = s[r + 1], | ||||||
|  |                         n = r + 2, | ||||||
|  |                         s[r + 1] = s[r + o], | ||||||
|  |                         s[o + r] = i, | ||||||
|  |                         (r = r + o + 1) - 2 > n)) | ||||||
|  |                             for (; n < r - 2; n++) | ||||||
|  |                                 s[n] = s[n] ^ e.charCodeAt(n % e.length); | ||||||
|  |                     for (r = 0; r < t.length; r++) | ||||||
|  |                         s[r] = s[r] ^ e.charCodeAt(r % e.length); | ||||||
|  |                     return s | ||||||
|  |                 } | ||||||
|  |                 for (var a = { | ||||||
|  |                     data: { | ||||||
|  |                         info: t | ||||||
|  |                     } | ||||||
|  |                 }, s = { | ||||||
|  |                     q: r, | ||||||
|  |                     h: n, | ||||||
|  |                     m: i, | ||||||
|  |                     k: o | ||||||
|  |                 }, l = a.data.info, u = l.substring(l.length - 4).split(''), c = 0; c < u.length; c++) | ||||||
|  |                     u[c] = u[c].toString().charCodeAt(0) % 4; | ||||||
|  |                 u.reverse(); | ||||||
|  |                 for (var d = [], c = 0; c < u.length; c++) | ||||||
|  |                     d.push(l.substring(u[c] + 1, u[c] + 2)), | ||||||
|  |                     l = l.substring(0, u[c] + 1) + l.substring(u[c] + 2); | ||||||
|  |                 a.data.encrypt_table = d, | ||||||
|  |                 a.data.key_table = []; | ||||||
|  |                 for (var c in a.data.encrypt_table) | ||||||
|  |                     'q' != a.data.encrypt_table[c] && 'k' != a.data.encrypt_table[c] || (a.data.key_table.push(l.substring(l.length - 12)), | ||||||
|  |                     l = l.substring(0, l.length - 12)); | ||||||
|  |                 a.data.key_table.reverse(), | ||||||
|  |                 a.data.info = l; | ||||||
|  |                 var f = new Array(-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,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,-1,-1,-1,-1,-1); | ||||||
|  |                 a.data.info = function(t) { | ||||||
|  |                     var e, r, n, i, o, a, s; | ||||||
|  |                     for (a = t.length, | ||||||
|  |                     o = 0, | ||||||
|  |                     s = ''; o < a; ) { | ||||||
|  |                         do { | ||||||
|  |                             e = f[255 & t.charCodeAt(o++)] | ||||||
|  |                         } while (o < a && -1 == e);if (-1 == e) | ||||||
|  |                             break; | ||||||
|  |                         do { | ||||||
|  |                             r = f[255 & t.charCodeAt(o++)] | ||||||
|  |                         } while (o < a && -1 == r);if (-1 == r) | ||||||
|  |                             break; | ||||||
|  |                         s += String.fromCharCode(e << 2 | (48 & r) >> 4); | ||||||
|  |                         do { | ||||||
|  |                             if (61 == (n = 255 & t.charCodeAt(o++))) | ||||||
|  |                                 return s; | ||||||
|  |                             n = f[n] | ||||||
|  |                         } while (o < a && -1 == n);if (-1 == n) | ||||||
|  |                             break; | ||||||
|  |                         s += String.fromCharCode((15 & r) << 4 | (60 & n) >> 2); | ||||||
|  |                         do { | ||||||
|  |                             if (61 == (i = 255 & t.charCodeAt(o++))) | ||||||
|  |                                 return s; | ||||||
|  |                             i = f[i] | ||||||
|  |                         } while (o < a && -1 == i);if (-1 == i) | ||||||
|  |                             break; | ||||||
|  |                         s += String.fromCharCode((3 & n) << 6 | i) | ||||||
|  |                     } | ||||||
|  |                     return s | ||||||
|  |                 }(a.data.info); | ||||||
|  |                 for (var c in a.data.encrypt_table) { | ||||||
|  |                     var h = a.data.encrypt_table[c]; | ||||||
|  |                     if ('q' == h || 'k' == h) { | ||||||
|  |                         var p = a.data.key_table.pop(); | ||||||
|  |                         a.data.info = s[a.data.encrypt_table[c]](a.data.info, p) | ||||||
|  |                     } else | ||||||
|  |                         a.data.info = s[a.data.encrypt_table[c]](a.data.info) | ||||||
|  |                 } | ||||||
|  |                 if (e) | ||||||
|  |                     return a.data.info; | ||||||
|  |                 var g = ''; | ||||||
|  |                 for (c = 0; c < a.data.info.length; c++) | ||||||
|  |                     g += String.fromCharCode(a.data.info[c]); | ||||||
|  |                 return g | ||||||
|  |             } | ||||||
|  |             function Uint8ArrayToString(fileData){ | ||||||
|  |               var dataString = ''; | ||||||
|  |               for (var i = 0; i < fileData.length; i++) { | ||||||
|  |                 dataString += Number(fileData[i]) + ','; | ||||||
|  |               } | ||||||
|  |               return dataString; | ||||||
|  |             } | ||||||
|  |             function decodeKey(resp){ | ||||||
|  |                 var string = eval('('+resp+')'); | ||||||
|  |                 //return btoa(String.fromCharCode.apply(null, new Uint8Array(n(string.data.info, 1)))); | ||||||
|  |                 return Uint8ArrayToString(new Uint8Array(n(string.data.info, 1))); | ||||||
|  |             } | ||||||
|  |             function decodeM3u8(resp){ | ||||||
|  |                 var string = eval('('+resp+')'); | ||||||
|  |                 return n(string.data.info); | ||||||
|  |             } | ||||||
|  |             "; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         public static string DecodeM3u8(string resp) | ||||||
|  |         { | ||||||
|  |             var context = new Context(); | ||||||
|  |             context.Eval(JS); | ||||||
|  |             var concatFunction = context.GetVariable("decodeM3u8").As<Function>(); | ||||||
|  |             string m3u8 = concatFunction.Call(new Arguments { resp }).ToString(); | ||||||
|  |             return m3u8; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static string DecodeKey(string resp) | ||||||
|  |         { | ||||||
|  |             var context = new Context(); | ||||||
|  |             context.Eval(JS); | ||||||
|  |             var concatFunction = context.GetVariable("decodeKey").As<Function>(); | ||||||
|  |             string key = concatFunction.Call(new Arguments { resp }).ToString(); | ||||||
|  |             byte[] v = Array.ConvertAll(key.Trim(',').Split(','), s => (byte)int.Parse(s)); | ||||||
|  |             string realKey = Convert.ToBase64String(v); | ||||||
|  |             return realKey; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								N_m3u8DL-CLI/DecodeNfmovies.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								N_m3u8DL-CLI/DecodeNfmovies.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | using System; | ||||||
|  | using System.IO; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     class DecodeNfmovies | ||||||
|  |     { | ||||||
|  |         //https://jx.nfmovies.com/hls.min.js | ||||||
|  |         public static string DecryptM3u8(byte[] byteArray) | ||||||
|  |         { | ||||||
|  |             var t = byteArray; | ||||||
|  |             var decrypt = ""; | ||||||
|  |             if (137 == t[0] && 80 == t[1] && 130 == t[354] && 96 == t[353]) t = t.Skip(355).ToArray(); | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 if (137 != t[0] || 80 != t[1] || 130 != t[394] || 96 != t[393]) | ||||||
|  |                 { | ||||||
|  |                     for (var i = 0; i < t.Length; i++) decrypt += Convert.ToChar(t[i]); | ||||||
|  |                     return decrypt; | ||||||
|  |                 } | ||||||
|  |                 t = t.Skip(395).ToArray(); | ||||||
|  |             } | ||||||
|  |             using (var zipStream = | ||||||
|  |                 new System.IO.Compression.GZipStream(new MemoryStream(t), System.IO.Compression.CompressionMode.Decompress)) | ||||||
|  |             { | ||||||
|  |                 using (StreamReader sr = new StreamReader(zipStream, Encoding.UTF8)) | ||||||
|  |                 { | ||||||
|  |                     decrypt = sr.ReadToEnd(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return decrypt; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										114
									
								
								N_m3u8DL-CLI/Decrypter.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								N_m3u8DL-CLI/Decrypter.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | |||||||
|  | using CSChaCha20; | ||||||
|  | using System; | ||||||
|  | using System.IO; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Security.Cryptography; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     class Decrypter | ||||||
|  |     { | ||||||
|  |         public static byte[] AES128Decrypt(string filePath, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7) | ||||||
|  |         { | ||||||
|  |             FileStream fs = new FileStream(filePath, FileMode.Open); | ||||||
|  |             //获取文件大小 | ||||||
|  |             long size = fs.Length; | ||||||
|  |             byte[] inBuff = new byte[size]; | ||||||
|  |             fs.Read(inBuff, 0, inBuff.Length); | ||||||
|  |             fs.Close(); | ||||||
|  |  | ||||||
|  |             Aes dcpt = Aes.Create(); | ||||||
|  |             dcpt.BlockSize = 128; | ||||||
|  |             dcpt.KeySize = 128; | ||||||
|  |             dcpt.Key = keyByte; | ||||||
|  |             dcpt.IV = ivByte; | ||||||
|  |             dcpt.Mode = mode; | ||||||
|  |             dcpt.Padding = padding; | ||||||
|  |  | ||||||
|  |             ICryptoTransform cTransform = dcpt.CreateDecryptor(); | ||||||
|  |             Byte[] resultArray = cTransform.TransformFinalBlock(inBuff, 0, inBuff.Length); | ||||||
|  |             return resultArray; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static byte[] AES128Decrypt(byte[] encryptedBuff, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7) | ||||||
|  |         { | ||||||
|  |             byte[] inBuff = encryptedBuff; | ||||||
|  |  | ||||||
|  |             Aes dcpt = Aes.Create(); | ||||||
|  |             dcpt.BlockSize = 128; | ||||||
|  |             dcpt.KeySize = 128; | ||||||
|  |             dcpt.Key = keyByte; | ||||||
|  |             dcpt.IV = ivByte; | ||||||
|  |             dcpt.Mode = mode; | ||||||
|  |             dcpt.Padding = padding; | ||||||
|  |  | ||||||
|  |             ICryptoTransform cTransform = dcpt.CreateDecryptor(); | ||||||
|  |             Byte[] resultArray = cTransform.TransformFinalBlock(inBuff, 0, inBuff.Length); | ||||||
|  |             return resultArray; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static byte[] CHACHA20Decrypt(byte[] encryptedBuff, byte[] keyBytes, byte[] nonceBytes) | ||||||
|  |         { | ||||||
|  |             if (keyBytes.Length != 32) | ||||||
|  |                 throw new Exception("Key must be 32 bytes!"); | ||||||
|  |             if (nonceBytes.Length != 12 && nonceBytes.Length != 8) | ||||||
|  |                 throw new Exception("Key must be 12 or 8 bytes!"); | ||||||
|  |             if (nonceBytes.Length == 8) | ||||||
|  |                 nonceBytes = (new byte[4] { 0, 0, 0, 0 }).Concat(nonceBytes).ToArray(); | ||||||
|  |  | ||||||
|  |             var decStream = new MemoryStream(); | ||||||
|  |             using (BinaryReader reader = new BinaryReader(new MemoryStream(encryptedBuff))) | ||||||
|  |             { | ||||||
|  |                 using (BinaryWriter writer = new BinaryWriter(decStream)) | ||||||
|  |                 { | ||||||
|  |                     while (true) | ||||||
|  |                     { | ||||||
|  |                         var buffer = reader.ReadBytes(1024); | ||||||
|  |                         byte[] dec = new byte[buffer.Length]; | ||||||
|  |                         if (buffer.Length > 0) | ||||||
|  |                         { | ||||||
|  |                             ChaCha20 forDecrypting = new ChaCha20(keyBytes, nonceBytes, 0); | ||||||
|  |                             forDecrypting.DecryptBytes(dec, buffer); | ||||||
|  |                             writer.Write(dec, 0, dec.Length); | ||||||
|  |                         } | ||||||
|  |                         else | ||||||
|  |                         { | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return decStream.ToArray(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static byte[] HexStringToBytes(string hexStr) | ||||||
|  |         { | ||||||
|  |             if (string.IsNullOrEmpty(hexStr)) | ||||||
|  |             { | ||||||
|  |                 return new byte[0]; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (hexStr.StartsWith("0x") || hexStr.StartsWith("0X")) | ||||||
|  |             { | ||||||
|  |                 hexStr = hexStr.Remove(0, 2); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             int count = hexStr.Length; | ||||||
|  |  | ||||||
|  |             if (count % 2 == 1) | ||||||
|  |             { | ||||||
|  |                 throw new ArgumentException("Invalid length of bytes:" + count); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             int byteCount = count / 2; | ||||||
|  |             byte[] result = new byte[byteCount]; | ||||||
|  |             for (int ii = 0; ii < byteCount; ++ii) | ||||||
|  |             { | ||||||
|  |                 var tempBytes = Byte.Parse(hexStr.Substring(2 * ii, 2), System.Globalization.NumberStyles.HexNumber); | ||||||
|  |                 result[ii] = tempBytes; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return result; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										668
									
								
								N_m3u8DL-CLI/DownloadManager.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										668
									
								
								N_m3u8DL-CLI/DownloadManager.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										265
									
								
								N_m3u8DL-CLI/Downloader.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										265
									
								
								N_m3u8DL-CLI/Downloader.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										177
									
								
								N_m3u8DL-CLI/FFmpeg.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								N_m3u8DL-CLI/FFmpeg.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,177 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Diagnostics; | ||||||
|  | using System.IO; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     class FFmpeg | ||||||
|  |     { | ||||||
|  |         public static string FFMPEG_PATH = "ffmpeg"; | ||||||
|  |         public static string REC_TIME = ""; //录制日期 | ||||||
|  |  | ||||||
|  |         public static string OutPutPath { get; set; } = string.Empty; | ||||||
|  |         public static string ReportFile { get; set; } = string.Empty; | ||||||
|  |         public static bool UseAACFilter { get; set; } = false;  //是否启用滤镜 | ||||||
|  |         public static bool WriteDate { get; set; } = true;  //是否写入录制日期 | ||||||
|  |  | ||||||
|  |         public static void Merge(string[] files, string muxFormat, bool fastStart, | ||||||
|  |             string poster = "", string audioName = "", string title = "", | ||||||
|  |             string copyright = "", string comment = "", string encodingTool = "") | ||||||
|  |         { | ||||||
|  |             string dateString = string.IsNullOrEmpty(REC_TIME) ? DateTime.Now.ToString("o") : REC_TIME; | ||||||
|  |  | ||||||
|  |             //同名文件已存在的共存策略 | ||||||
|  |             if (File.Exists($"{OutPutPath}.{muxFormat.ToLower()}"))  | ||||||
|  |             { | ||||||
|  |                 OutPutPath = Path.Combine(Path.GetDirectoryName(OutPutPath), | ||||||
|  |                     Path.GetFileName(OutPutPath) + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             string command = "-loglevel warning -i concat:\""; | ||||||
|  |             string data = string.Empty; | ||||||
|  |             string ddpAudio = string.Empty; | ||||||
|  |             string addPoster = "-map 1 -c:v:1 copy -disposition:v:1 attached_pic"; | ||||||
|  |             ddpAudio = (File.Exists($"{Path.GetFileNameWithoutExtension(OutPutPath + ".mp4")}.txt") ? File.ReadAllText($"{Path.GetFileNameWithoutExtension(OutPutPath + ".mp4")}.txt") : "") ; | ||||||
|  |             if (!string.IsNullOrEmpty(ddpAudio)) UseAACFilter = false; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |             foreach (string t in files) | ||||||
|  |             { | ||||||
|  |                 command += Path.GetFileName(t) + "|"; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             switch (muxFormat.ToUpper()) | ||||||
|  |             { | ||||||
|  |                 case ("MP4"): | ||||||
|  |                     command += "\" " + (string.IsNullOrEmpty(poster) ? "" : "-i \"" + poster + "\""); | ||||||
|  |                     command += " " + (string.IsNullOrEmpty(ddpAudio) ? "" : "-i \"" + ddpAudio + "\""); | ||||||
|  |                     command += | ||||||
|  |                         $" -map 0:v? {(string.IsNullOrEmpty(ddpAudio) ? "-map 0:a?" : $"-map {(string.IsNullOrEmpty(poster) ? "1" : "2")}:a -map 0:a?")} -map 0:s? " + (string.IsNullOrEmpty(poster) ? "" : addPoster) | ||||||
|  |                         + (WriteDate ? " -metadata date=\"" + dateString + "\"" : "") + | ||||||
|  |                         " -metadata encoding_tool=\"" + encodingTool + "\" -metadata title=\"" + title + | ||||||
|  |                         "\" -metadata copyright=\"" + copyright + "\" -metadata comment=\"" + comment + | ||||||
|  |                         $"\" -metadata:s:a:{(string.IsNullOrEmpty(ddpAudio) ? "0" : "1")} handler_name=\"" + audioName + $"\" -metadata:s:a:{(string.IsNullOrEmpty(ddpAudio) ? "0" : "1")} handler=\"" + audioName + "\" "; | ||||||
|  |                     command += (string.IsNullOrEmpty(ddpAudio) ? "" : " -metadata:s:a:0 handler_name=\"DD+\" -metadata:s:a:0 handler=\"DD+\" "); | ||||||
|  |                     if (fastStart) | ||||||
|  |                         command += "-movflags +faststart"; | ||||||
|  |                     command += "  -c copy -y " + (UseAACFilter ? "-bsf:a aac_adtstoasc" : "") + " \"" + OutPutPath + ".mp4\""; | ||||||
|  |                     break; | ||||||
|  |                 case ("MKV"): | ||||||
|  |                     command += "\" -map 0  -c copy -y " + (UseAACFilter ? "-bsf:a aac_adtstoasc" : "") + " \"" + OutPutPath + ".mkv\""; | ||||||
|  |                     break; | ||||||
|  |                 case ("FLV"): | ||||||
|  |                     command += "\" -map 0  -c copy -y " + (UseAACFilter ? "-bsf:a aac_adtstoasc" : "") + " \"" + OutPutPath + ".flv\""; | ||||||
|  |                     break; | ||||||
|  |                 case ("TS"): | ||||||
|  |                     command += "\" -map 0  -c copy -y -f mpegts -bsf:v h264_mp4toannexb \"" + OutPutPath + ".ts\""; | ||||||
|  |                     break; | ||||||
|  |                 case ("VTT"): | ||||||
|  |                     command += "\" -map 0  -y \"" + OutPutPath + ".srt\"";  //Convert To Srt | ||||||
|  |                     break; | ||||||
|  |                 case ("EAC3"): | ||||||
|  |                     command += "\" -map 0:a -c copy -y \"" + OutPutPath + ".eac3\""; | ||||||
|  |                     break; | ||||||
|  |                 case ("AAC"): | ||||||
|  |                     command += "\" -map 0:a -c copy -y \"" + OutPutPath + ".m4a\""; | ||||||
|  |                     break; | ||||||
|  |                 case ("AC3"): | ||||||
|  |                     command += "\" -map 0:a -c copy -y \"" + OutPutPath + ".ac3\""; | ||||||
|  |                     break; | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             Run(FFMPEG_PATH, command, Path.GetDirectoryName(files[0])); | ||||||
|  |             LOGGER.WriteLine(strings.ffmpegDone); | ||||||
|  |             //Console.WriteLine(command); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static void ConvertToMPEGTS(string file) | ||||||
|  |         { | ||||||
|  |             if (Global.VIDEO_TYPE == "H264") | ||||||
|  |             { | ||||||
|  |                 Run(FFMPEG_PATH, | ||||||
|  |                     "-loglevel quiet -i \"" + file + "\" -map 0 -c copy -copy_unknown -f mpegts -bsf:v h264_mp4toannexb \"" | ||||||
|  |                     + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts\"",  | ||||||
|  |                     Path.GetDirectoryName(file)); | ||||||
|  |                 if (File.Exists(Path.GetDirectoryName(file) + "\\" + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts")) | ||||||
|  |                 { | ||||||
|  |                     File.Delete(file); | ||||||
|  |                     File.Move(Path.GetDirectoryName(file) + "\\" + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts", file); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else if (Global.VIDEO_TYPE == "H265") | ||||||
|  |             { | ||||||
|  |                 Run(FFMPEG_PATH, | ||||||
|  |                     "-loglevel quiet -i \"" + file + "\" -map 0 -c copy -copy_unknown -f mpegts -bsf:v hevc_mp4toannexb \"" | ||||||
|  |                     + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts\"", | ||||||
|  |                     Path.GetDirectoryName(file)); | ||||||
|  |                 if (File.Exists(Path.GetDirectoryName(file) + "\\" + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts")) | ||||||
|  |                 { | ||||||
|  |                     File.Delete(file); | ||||||
|  |                     File.Move(Path.GetDirectoryName(file) + "\\" + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts", file); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 LOGGER.WriteLineError("Unkown Video Type"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static void Run(string path, string args, string workDir) | ||||||
|  |         { | ||||||
|  |             string nowDir = Directory.GetCurrentDirectory();  //当前工作路径 | ||||||
|  |             Directory.SetCurrentDirectory(workDir); | ||||||
|  |             Process p = new Process();//建立外部调用线程 | ||||||
|  |             p.StartInfo.FileName = path;//要调用外部程序的绝对路径 | ||||||
|  |             Environment.SetEnvironmentVariable("FFREPORT", "file=" + ReportFile + ":level=32"); //兼容XP系统 | ||||||
|  |             //p.StartInfo.Environment.Add("FFREPORT", "file=" + ReportFile + ":level=32"); | ||||||
|  |             p.StartInfo.Arguments = args;//参数(这里就是FFMPEG的参数了) | ||||||
|  |             p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN) | ||||||
|  |             p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的) | ||||||
|  |             p.StartInfo.CreateNoWindow = false;//不创建进程窗口 | ||||||
|  |             p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN | ||||||
|  |             p.StartInfo.StandardErrorEncoding = Encoding.UTF8; | ||||||
|  |             p.Start();//启动线程 | ||||||
|  |             p.BeginErrorReadLine();//开始异步读取 | ||||||
|  |             p.WaitForExit();//阻塞等待进程结束 | ||||||
|  |             p.Close();//关闭进程 | ||||||
|  |             p.Dispose();//释放资源 | ||||||
|  |             Environment.SetEnvironmentVariable("FFREPORT", null); //兼容XP系统 | ||||||
|  |             Directory.SetCurrentDirectory(nowDir); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static void Output(object sendProcess, DataReceivedEventArgs output) | ||||||
|  |         { | ||||||
|  |             if (!String.IsNullOrEmpty(output.Data)) | ||||||
|  |             { | ||||||
|  |                 LOGGER.PrintLine(output.Data, LOGGER.Warning); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static bool CheckMPEGTS(string file) | ||||||
|  |         { | ||||||
|  |             //放行杜比视界或纯音频文件 | ||||||
|  |             if (Global.VIDEO_TYPE == "DV" || Global.AUDIO_TYPE != "") | ||||||
|  |                 return true; | ||||||
|  |             //如果是多分片,也认为不是MPEGTS | ||||||
|  |             if (DownloadManager.PartsCount > 1) | ||||||
|  |                 return false; | ||||||
|  |  | ||||||
|  |             using (FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))  | ||||||
|  |             { | ||||||
|  |                 byte[] firstByte = new byte[1]; | ||||||
|  |                 fs.Read(firstByte, 0, 1); | ||||||
|  |                 //第一字节的16进制字符串 | ||||||
|  |                 string _1_byte_str = Convert.ToString(firstByte[0], 16); | ||||||
|  |                 //syncword不为47就不处理 | ||||||
|  |                 if (_1_byte_str != "47") | ||||||
|  |                     return false; | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										1284
									
								
								N_m3u8DL-CLI/Global.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1284
									
								
								N_m3u8DL-CLI/Global.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										155
									
								
								N_m3u8DL-CLI/HLSLiveDownloader.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								N_m3u8DL-CLI/HLSLiveDownloader.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | |||||||
|  | using Newtonsoft.Json.Linq; | ||||||
|  | using System; | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.IO; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading; | ||||||
|  | using System.Timers; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     class HLSLiveDownloader | ||||||
|  |     { | ||||||
|  |         public static int REC_DUR_LIMIT = -1; //默认不限制录制时长 | ||||||
|  |         public static double REC_DUR = 0; //已录制时长 | ||||||
|  |         private string liveFile = string.Empty; | ||||||
|  |         private string jsonFile = string.Empty; | ||||||
|  |         private string headers = string.Empty; | ||||||
|  |         private string downDir = string.Empty; | ||||||
|  |         private FileStream liveStream = null; | ||||||
|  |         private double targetduration = 10; | ||||||
|  |         private bool isFirstJson = true; | ||||||
|  |  | ||||||
|  |         public double TotalDuration { get; set; } | ||||||
|  |         public string Headers { get => headers; set => headers = value; } | ||||||
|  |         public string DownDir { get => downDir; set => downDir = value; } | ||||||
|  |         public FileStream LiveStream { get => liveStream; set => liveStream = value; } | ||||||
|  |         public string LiveFile { get => liveFile; set => liveFile = value; } | ||||||
|  |  | ||||||
|  |         ArrayList toDownList = new ArrayList();  //所有待下载的列表 | ||||||
|  |         System.Timers.Timer timer = new System.Timers.Timer(); | ||||||
|  |         Downloader sd = new Downloader();  //只有一个实例 | ||||||
|  |  | ||||||
|  |         public void TimerStart() | ||||||
|  |         { | ||||||
|  |             timer.Enabled = true; | ||||||
|  |             //timer.Interval = (targetduration - 2) * 1000; //执行间隔时间,单位为毫秒 | ||||||
|  |             timer.Start(); | ||||||
|  |             timer.Elapsed += new ElapsedEventHandler(UpdateList); | ||||||
|  |             UpdateList(timer, new EventArgs());  //立即执行一次 | ||||||
|  |             Record(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void TimerStop() | ||||||
|  |         { | ||||||
|  |             timer.Stop(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         //更新列表 | ||||||
|  |         private void UpdateList(object source, EventArgs e) | ||||||
|  |         { | ||||||
|  |             jsonFile = Path.Combine(DownDir, "meta.json"); | ||||||
|  |             if (!File.Exists(jsonFile))  | ||||||
|  |             { | ||||||
|  |                 TimerStop(); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             string jsonContent = File.ReadAllText(jsonFile); | ||||||
|  |             JObject initJson = JObject.Parse(jsonContent); | ||||||
|  |             string m3u8Url = initJson["m3u8"].Value<string>(); | ||||||
|  |             targetduration = initJson["m3u8Info"]["targetDuration"].Value<double>(); | ||||||
|  |             TotalDuration = initJson["m3u8Info"]["totalDuration"].Value<double>(); | ||||||
|  |             timer.Interval = (TotalDuration - targetduration) * 1000;//设置定时器运行间隔 | ||||||
|  |             if (timer.Interval <= 1000) timer.Interval = 10000; | ||||||
|  |             JArray lastSegments = JArray.Parse(initJson["m3u8Info"]["segments"][0].ToString().Trim());  //上次的分段,用于比对新分段 | ||||||
|  |             ArrayList tempList = new ArrayList();  //所有待下载的列表 | ||||||
|  |             tempList.Clear(); | ||||||
|  |             foreach (JObject seg in lastSegments) | ||||||
|  |             { | ||||||
|  |                 tempList.Add(seg.ToString()); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(isFirstJson) | ||||||
|  |             { | ||||||
|  |                 toDownList = tempList; | ||||||
|  |                 isFirstJson = false; | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             Parser parser = new Parser(); | ||||||
|  |             parser.DownDir = Path.GetDirectoryName(jsonFile); | ||||||
|  |             parser.M3u8Url = m3u8Url; | ||||||
|  |             parser.LiveStream = true; | ||||||
|  |             parser.Parse();  //产生新的json文件 | ||||||
|  |  | ||||||
|  |             jsonContent = File.ReadAllText(jsonFile); | ||||||
|  |             initJson = JObject.Parse(jsonContent); | ||||||
|  |             JArray segments = JArray.Parse(initJson["m3u8Info"]["segments"][0].ToString());  //大分组 | ||||||
|  |             foreach (JObject seg in segments) | ||||||
|  |             { | ||||||
|  |                 if (!tempList.Contains(seg.ToString())) | ||||||
|  |                 { | ||||||
|  |                     toDownList.Add(seg.ToString());  //加入真正的待下载队列 | ||||||
|  |                     //Console.WriteLine(seg.ToString()); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             if (toDownList.Count > 0) | ||||||
|  |                 Record(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         //public void TryDownload() | ||||||
|  |         //{ | ||||||
|  |         //    Thread t = new Thread(Download); | ||||||
|  |         //    while (toDownList.Count != 0) | ||||||
|  |         //    { | ||||||
|  |         //        t = new Thread(Download); | ||||||
|  |         //        t.Start(); | ||||||
|  |         //        t.Join(); | ||||||
|  |         //        while (sd.IsDone != true) ;  //忙等待 | ||||||
|  |         //        if (toDownList.Count > 0) | ||||||
|  |         //            toDownList.RemoveAt(0);  //下完删除一项 | ||||||
|  |         //    } | ||||||
|  |         //    Console.WriteLine("Waiting..."); | ||||||
|  |         //} | ||||||
|  |  | ||||||
|  |         private void Record() | ||||||
|  |         { | ||||||
|  |             while (toDownList.Count > 0 && (sd.FileUrl != "" ? sd.IsDone : true))  | ||||||
|  |             { | ||||||
|  |                 JObject info = JObject.Parse(toDownList[0].ToString()); | ||||||
|  |                 int index = info["index"].Value<int>(); | ||||||
|  |                 sd.FileUrl = info["segUri"].Value<string>(); | ||||||
|  |                 sd.Method = info["method"].Value<string>(); | ||||||
|  |                 if (sd.Method != "NONE") | ||||||
|  |                 { | ||||||
|  |                     sd.Key = info["key"].Value<string>(); | ||||||
|  |                     sd.Iv = info["iv"].Value<string>(); | ||||||
|  |                 } | ||||||
|  |                 sd.TimeOut = (int)timer.Interval - 1000;//超时时间不超过下次执行时间 | ||||||
|  |                 if (sd.TimeOut <= 0) sd.TimeOut = (int)timer.Interval; | ||||||
|  |                 sd.SegIndex = index; | ||||||
|  |                 sd.Headers = Headers; | ||||||
|  |                 sd.SegDur = info["duration"].Value<double>(); | ||||||
|  |                 sd.IsLive = true;  //标记为直播 | ||||||
|  |                 sd.LiveFile = LiveFile; | ||||||
|  |                 sd.LiveStream = LiveStream; | ||||||
|  |                 sd.Down();  //开始下载 | ||||||
|  |                 while (sd.IsDone != true) { Thread.Sleep(1); };  //忙等待 Thread.Sleep(1) 可防止cpu 100% 防止电脑风扇狂转 | ||||||
|  |                 if (toDownList.Count > 0) | ||||||
|  |                     toDownList.RemoveAt(0);  //下完删除一项 | ||||||
|  |             } | ||||||
|  |             LOGGER.PrintLine("Waiting...", LOGGER.Warning); | ||||||
|  |             LOGGER.WriteLine("Waiting..."); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         //检测是否有新分片 | ||||||
|  |         private bool isNewSeg() | ||||||
|  |         { | ||||||
|  |             if (toDownList.Count > 0) | ||||||
|  |                 return true; | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								N_m3u8DL-CLI/HLSTags.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								N_m3u8DL-CLI/HLSTags.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     class HLSTags | ||||||
|  |     { | ||||||
|  |         public static string ext_m3u = "#EXTM3U"; | ||||||
|  |         public static string ext_x_targetduration = "#EXT-X-TARGETDURATION"; | ||||||
|  |         public static string ext_x_media_sequence = "#EXT-X-MEDIA-SEQUENCE"; | ||||||
|  |         public static string ext_x_discontinuity_sequence = "#EXT-X-DISCONTINUITY-SEQUENCE"; | ||||||
|  |         public static string ext_x_program_date_time = "#EXT-X-PROGRAM-DATE-TIME"; | ||||||
|  |         public static string ext_x_media = "#EXT-X-MEDIA"; | ||||||
|  |         public static string ext_x_playlist_type = "#EXT-X-PLAYLIST-TYPE"; | ||||||
|  |         public static string ext_x_key = "#EXT-X-KEY"; | ||||||
|  |         public static string ext_x_stream_inf = "#EXT-X-STREAM-INF"; | ||||||
|  |         public static string ext_x_version = "#EXT-X-VERSION"; | ||||||
|  |         public static string ext_x_allow_cache = "#EXT-X-ALLOW-CACHE"; | ||||||
|  |         public static string ext_x_endlist = "#EXT-X-ENDLIST"; | ||||||
|  |         public static string extinf = "#EXTINF"; | ||||||
|  |         public static string ext_i_frames_only = "#EXT-X-I-FRAMES-ONLY"; | ||||||
|  |         public static string ext_x_byterange = "#EXT-X-BYTERANGE"; | ||||||
|  |         public static string ext_x_i_frame_stream_inf = "#EXT-X-I-FRAME-STREAM-INF"; | ||||||
|  |         public static string ext_x_discontinuity = "#EXT-X-DISCONTINUITY"; | ||||||
|  |         public static string ext_x_cue_out_start = "#EXT-X-CUE-OUT"; | ||||||
|  |         public static string ext_x_cue_out = "#EXT-X-CUE-OUT-CONT"; | ||||||
|  |         public static string ext_is_independent_segments = "#EXT-X-INDEPENDENT-SEGMENTS"; | ||||||
|  |         public static string ext_x_scte35 = "#EXT-OATCLS-SCTE35"; | ||||||
|  |         public static string ext_x_cue_start = "#EXT-X-CUE-OUT"; | ||||||
|  |         public static string ext_x_cue_end = "#EXT-X-CUE-IN"; | ||||||
|  |         public static string ext_x_cue_span = "#EXT-X-CUE-SPAN"; | ||||||
|  |         public static string ext_x_map = "#EXT-X-MAP"; | ||||||
|  |         public static string ext_x_start = "#EXT-X-START"; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										116
									
								
								N_m3u8DL-CLI/IqJsonParser.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								N_m3u8DL-CLI/IqJsonParser.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | |||||||
|  | using Newtonsoft.Json.Linq; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.IO; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     class IqJsonParser | ||||||
|  |     { | ||||||
|  |         public static string Parse(string downDir, string json) | ||||||
|  |         { | ||||||
|  |             JObject jObject = JObject.Parse(json); | ||||||
|  |             var aClips = jObject["payload"]["wm_a"]["audio_track1"]["files"].Value<JArray>(); | ||||||
|  |             var vClips = jObject["payload"]["wm_a"]["video_track1"]["files"].Value<JArray>(); | ||||||
|  |  | ||||||
|  |             var codecsList = new List<string>(); | ||||||
|  |  | ||||||
|  |             var audioPath = ""; | ||||||
|  |             var videoPath = ""; | ||||||
|  |             var audioInitPath = ""; | ||||||
|  |             var videoInitPath = ""; | ||||||
|  |  | ||||||
|  |             if (aClips.Count > 0) | ||||||
|  |             { | ||||||
|  |                 var init = jObject["payload"]["wm_a"]["audio_track1"]["codec_init"].Value<string>(); | ||||||
|  |                 byte[] bytes = Convert.FromBase64String(init); | ||||||
|  |                 //输出init文件 | ||||||
|  |                 audioInitPath = Path.Combine(downDir, "iqAudioInit.mp4"); | ||||||
|  |                 File.WriteAllBytes(audioInitPath, bytes); | ||||||
|  |                 StringBuilder sb = new StringBuilder(); | ||||||
|  |                 sb.AppendLine("#EXTM3U"); | ||||||
|  |                 sb.AppendLine("#EXT-X-VERSION:3"); | ||||||
|  |                 sb.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD"); | ||||||
|  |                 sb.AppendLine("#CREATED-BY:N_m3u8DL-CLI"); | ||||||
|  |                 sb.AppendLine($"#EXT-CODEC:{jObject["payload"]["wm_a"]["audio_track1"]["codec"].Value<string>()}"); | ||||||
|  |                 sb.AppendLine($"#EXT-KID:{jObject["payload"]["wm_a"]["audio_track1"]["key_id"].Value<string>()}"); | ||||||
|  |                 sb.AppendLine($"#EXT-X-MAP:URI=\"{new Uri(Path.Combine(downDir + "(Audio)", "iqAudioInit.mp4")).ToString()}\""); | ||||||
|  |                 sb.AppendLine("#EXT-X-KEY:METHOD=PLZ-KEEP-RAW,URI=\"None\""); | ||||||
|  |                 foreach (var a in aClips) | ||||||
|  |                 { | ||||||
|  |                     sb.AppendLine($"#EXTINF:{a["duration_second"].ToString()}"); | ||||||
|  |                     sb.AppendLine(a["file_name"].Value<string>()); | ||||||
|  |                 } | ||||||
|  |                 sb.AppendLine("#EXT-X-ENDLIST"); | ||||||
|  |                 //输出m3u8文件 | ||||||
|  |                 var _path = Path.Combine(downDir, "iqAudio.m3u8"); | ||||||
|  |                 File.WriteAllText(_path, sb.ToString()); | ||||||
|  |                 audioPath = new Uri(_path).ToString(); | ||||||
|  |                 codecsList.Add(jObject["payload"]["wm_a"]["audio_track1"]["codec"].Value<string>()); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (vClips.Count > 0) | ||||||
|  |             { | ||||||
|  |                 var init = jObject["payload"]["wm_a"]["video_track1"]["codec_init"].Value<string>(); | ||||||
|  |                 byte[] bytes = Convert.FromBase64String(init); | ||||||
|  |                 //输出init文件 | ||||||
|  |                 videoInitPath = Path.Combine(downDir, "iqVideoInit.mp4"); | ||||||
|  |                 File.WriteAllBytes(videoInitPath, bytes); | ||||||
|  |                 StringBuilder sb = new StringBuilder(); | ||||||
|  |                 sb.AppendLine("#EXTM3U"); | ||||||
|  |                 sb.AppendLine("#EXT-X-VERSION:3"); | ||||||
|  |                 sb.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD"); | ||||||
|  |                 sb.AppendLine("#CREATED-BY:N_m3u8DL-CLI"); | ||||||
|  |                 sb.AppendLine($"#EXT-CODEC:{jObject["payload"]["wm_a"]["video_track1"]["codec"].Value<string>()}"); | ||||||
|  |                 sb.AppendLine($"#EXT-KID:{jObject["payload"]["wm_a"]["video_track1"]["key_id"].Value<string>()}"); | ||||||
|  |                 sb.AppendLine($"#EXT-X-MAP:URI=\"{new Uri(videoInitPath).ToString()}\""); | ||||||
|  |                 sb.AppendLine("#EXT-X-KEY:METHOD=PLZ-KEEP-RAW,URI=\"None\""); | ||||||
|  |                 foreach (var a in vClips) | ||||||
|  |                 { | ||||||
|  |                     var start = a["seekable"]["pos_start"].Value<long>(); | ||||||
|  |                     var size = a["size"].Value<long>(); | ||||||
|  |                     sb.AppendLine($"#EXTINF:{a["duration_second"].ToString()}"); | ||||||
|  |                     sb.AppendLine($"#EXT-X-BYTERANGE:{size}@{start}"); | ||||||
|  |                     sb.AppendLine(a["file_name"].Value<string>()); | ||||||
|  |                 } | ||||||
|  |                 sb.AppendLine("#EXT-X-ENDLIST"); | ||||||
|  |                 //输出m3u8文件 | ||||||
|  |                 var _path = Path.Combine(downDir, "iqVideo.m3u8"); | ||||||
|  |                 File.WriteAllText(_path, sb.ToString()); | ||||||
|  |                 videoPath = new Uri(_path).ToString(); | ||||||
|  |                 codecsList.Add(jObject["payload"]["wm_a"]["video_track1"]["codec"].Value<string>()); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var content = ""; | ||||||
|  |             if ((videoPath == "" && audioPath != "") || Global.VIDEO_TYPE == "IGNORE") | ||||||
|  |             { | ||||||
|  |                 return audioPath; | ||||||
|  |             } | ||||||
|  |             else if (audioPath == "" && videoPath != "") | ||||||
|  |             { | ||||||
|  |                 return videoPath; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 if (!Directory.Exists(downDir + "(Audio)")) | ||||||
|  |                     Directory.CreateDirectory(downDir + "(Audio)"); | ||||||
|  |                 var _path = Path.Combine(downDir + "(Audio)", "iqAudio.m3u8"); | ||||||
|  |                 var _pathInit = Path.Combine(downDir + "(Audio)", "iqAudioInit.mp4"); | ||||||
|  |                 File.Copy(new Uri(audioPath).LocalPath, _path, true); | ||||||
|  |                 File.Copy(new Uri(audioInitPath).LocalPath, _pathInit, true); | ||||||
|  |                 audioPath = new Uri(_path).ToString(); | ||||||
|  |                 content = $"#EXTM3U\r\n" + | ||||||
|  |                     $"#EXT-X-MEDIA:TYPE=AUDIO,URI=\"{audioPath}\",GROUP-ID=\"default-audio-group\",NAME=\"stream_0\",AUTOSELECT=YES,CHANNELS=\"0\"\r\n" + | ||||||
|  |                     $"#EXT-X-STREAM-INF:BANDWIDTH=99999,CODECS=\"{string.Join(",", codecsList)}\",RESOLUTION=0x0,AUDIO=\"default-audio-group\"\r\n" + | ||||||
|  |                     $"{videoPath}"; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var _masterPath = Path.Combine(downDir, "master.m3u8"); | ||||||
|  |             File.WriteAllText(_masterPath, content); | ||||||
|  |             return new Uri(_masterPath).ToString(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										163
									
								
								N_m3u8DL-CLI/LOGGER.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								N_m3u8DL-CLI/LOGGER.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,163 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Diagnostics; | ||||||
|  | using System.IO; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     class LOGGER | ||||||
|  |     { | ||||||
|  |         public const int Default = 1; | ||||||
|  |         public const int Error = 2; | ||||||
|  |         public const int Warning = 3; | ||||||
|  |  | ||||||
|  |         public static string LOGFILE; | ||||||
|  |         public static bool STOPLOG = false; | ||||||
|  |         public static string FindLog(string dir) | ||||||
|  |         { | ||||||
|  |             DirectoryInfo d = new DirectoryInfo(dir); | ||||||
|  |             foreach (FileInfo fi in d.GetFiles()) | ||||||
|  |             { | ||||||
|  |                 if (fi.Extension.ToUpper() == ".LOG") | ||||||
|  |                 { | ||||||
|  |                     return fi.FullName; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return ""; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static void InitLog() | ||||||
|  |         { | ||||||
|  |             if (!Directory.Exists(Path.GetDirectoryName(LOGFILE)))//若文件夹不存在则新建文件夹    | ||||||
|  |                 Directory.CreateDirectory(Path.GetDirectoryName(LOGFILE)); //新建文件夹 | ||||||
|  |             //若文件存在则加序号 | ||||||
|  |             int index = 1; | ||||||
|  |             var fileName = Path.GetFileNameWithoutExtension(LOGFILE); | ||||||
|  |             while (File.Exists(LOGFILE)) | ||||||
|  |             { | ||||||
|  |                 LOGFILE = Path.Combine(Path.GetDirectoryName(LOGFILE), $"{fileName}-{index++}.log"); | ||||||
|  |             } | ||||||
|  |             string file = LOGFILE; | ||||||
|  |             string now = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"); | ||||||
|  |             string init = "LOG " + DateTime.Now.ToString("yyyy/MM/dd") + "\r\n" | ||||||
|  |                 + "Save Path: " + Path.GetDirectoryName(LOGFILE) + "\r\n" | ||||||
|  |                 + "Task Start: " + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + "\r\n" | ||||||
|  |                 + "Task CommandLine: " + Environment.CommandLine; | ||||||
|  |  | ||||||
|  |             if (File.Exists(Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), "N_m3u8DL-CLI.args.txt"))) | ||||||
|  |             { | ||||||
|  |                 init += "\r\nAdditional Args: " + File.ReadAllText(Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), "N_m3u8DL-CLI.args.txt"));  //解析命令行 | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             init += "\r\n\r\n"; | ||||||
|  |             File.WriteAllText(file, init, Encoding.UTF8); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         //读写锁机制,当资源被占用,其他线程等待 | ||||||
|  |         static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim(); | ||||||
|  |  | ||||||
|  |         public static void PrintLine(string text, int printLevel = 1) | ||||||
|  |         { | ||||||
|  |             int windowWith = 63; | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 windowWith = Console.WindowWidth; | ||||||
|  |             } | ||||||
|  |             catch (Exception e) | ||||||
|  |             { | ||||||
|  |                // empty | ||||||
|  |             } | ||||||
|  |             switch (printLevel) | ||||||
|  |             { | ||||||
|  |                 case 0: | ||||||
|  |                     Console.Write("\r" + new string(' ', windowWith - 1) + "\r"); | ||||||
|  |                     Console.WriteLine(" ".PadRight(12) + " " + text); | ||||||
|  |                     break; | ||||||
|  |                 case 1: | ||||||
|  |                     Console.Write("\r" + new string(' ', windowWith - 1) + "\r"); | ||||||
|  |                     Console.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " "); | ||||||
|  |                     Console.WriteLine(text); | ||||||
|  |                     break; | ||||||
|  |                 case 2: | ||||||
|  |                     Console.Write("\r" + new string(' ', windowWith - 1) + "\r"); | ||||||
|  |                     Console.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " "); | ||||||
|  |                     Console.ForegroundColor = ConsoleColor.Red; | ||||||
|  |                     Console.WriteLine(text); | ||||||
|  |                     Console.ResetColor(); | ||||||
|  |                     break; | ||||||
|  |                 case 3: | ||||||
|  |                     Console.Write("\r" + new string(' ', windowWith - 1) + "\r"); | ||||||
|  |                     Console.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " "); | ||||||
|  |                     Console.ForegroundColor = ConsoleColor.DarkYellow; | ||||||
|  |                     Console.WriteLine(text); | ||||||
|  |                     Console.ResetColor(); | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static void WriteLine(string text) | ||||||
|  |         { | ||||||
|  |             if (STOPLOG) | ||||||
|  |                 return; | ||||||
|  |             if (!File.Exists(LOGFILE)) | ||||||
|  |                 return; | ||||||
|  |  | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 string file = LOGFILE; | ||||||
|  |                 //进入写入 | ||||||
|  |                 LogWriteLock.EnterWriteLock(); | ||||||
|  |                 using (StreamWriter sw = File.AppendText(file)) | ||||||
|  |                 { | ||||||
|  |                     sw.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " / (NORMAL) " + text, Encoding.UTF8); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             catch (Exception) | ||||||
|  |             { | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |             finally | ||||||
|  |             { | ||||||
|  |                 //释放占用 | ||||||
|  |                 LogWriteLock.ExitWriteLock(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static void WriteLineError(string text) | ||||||
|  |         { | ||||||
|  |             if (!File.Exists(LOGFILE)) | ||||||
|  |                 return; | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 string file = LOGFILE; | ||||||
|  |                 //进入写入 | ||||||
|  |                 LogWriteLock.EnterWriteLock(); | ||||||
|  |                 using (StreamWriter sw = File.AppendText(file)) | ||||||
|  |                 { | ||||||
|  |                     sw.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " / (ERROR) " + text, Encoding.UTF8); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             catch (Exception) | ||||||
|  |             { | ||||||
|  |  | ||||||
|  |             } | ||||||
|  |             finally | ||||||
|  |             { | ||||||
|  |                 //释放占用 | ||||||
|  |                 LogWriteLock.ExitWriteLock(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static void Show(string text) | ||||||
|  |         { | ||||||
|  |             Console.ForegroundColor = ConsoleColor.Red; | ||||||
|  |             Console.WriteLine(DateTime.Now.ToString("o") + "  " + text); | ||||||
|  |             while (Console.ForegroundColor == ConsoleColor.Red) | ||||||
|  |                 Console.ResetColor(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										867
									
								
								N_m3u8DL-CLI/MPDParser.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										867
									
								
								N_m3u8DL-CLI/MPDParser.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										110
									
								
								N_m3u8DL-CLI/MyOptions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								N_m3u8DL-CLI/MyOptions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | |||||||
|  | using CommandLine; | ||||||
|  | using CommandLine.Text; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     internal class MyOptions | ||||||
|  |     { | ||||||
|  |         [Value(0, Hidden = true, MetaName = "Input Source", HelpText = "Help_input", ResourceType = typeof(strings))] | ||||||
|  |         public string Input { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("workDir", HelpText = "Help_workDir", ResourceType = typeof(strings))] | ||||||
|  |         public string WorkDir { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("saveName", HelpText = "Help_saveName", ResourceType = typeof(strings))] | ||||||
|  |         public string SaveName { get; set; } = ""; | ||||||
|  |  | ||||||
|  |         [Option("baseUrl", HelpText = "Help_baseUrl", ResourceType = typeof(strings))] | ||||||
|  |         public string BaseUrl { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("headers", HelpText = "Help_headers", ResourceType = typeof(strings))] | ||||||
|  |         public string Headers { get; set; } = ""; | ||||||
|  |  | ||||||
|  |         [Option("maxThreads", Default = 32U, HelpText = "Help_maxThreads", ResourceType = typeof(strings))] | ||||||
|  |         public uint MaxThreads { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("minThreads", Default = 16U, HelpText = "Help_minThreads", ResourceType = typeof(strings))] | ||||||
|  |         public uint MinThreads { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("retryCount", Default = 15U, HelpText = "Help_retryCount", ResourceType = typeof(strings))] | ||||||
|  |         public uint RetryCount { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("timeOut", Default = 10U, HelpText = "Help_timeOut", ResourceType = typeof(strings))] | ||||||
|  |         public uint TimeOut { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("muxSetJson", HelpText = "Help_muxSetJson", ResourceType = typeof(strings))] | ||||||
|  |         public string MuxSetJson { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("useKeyFile", HelpText = "Help_useKeyFile", ResourceType = typeof(strings))] | ||||||
|  |         public string UseKeyFile { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("useKeyBase64", HelpText = "Help_useKeyBase64", ResourceType = typeof(strings))] | ||||||
|  |         public string UseKeyBase64 { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("useKeyIV", HelpText = "Help_useKeyIV", ResourceType = typeof(strings))] | ||||||
|  |         public string UseKeyIV { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("downloadRange", HelpText = "Help_downloadRange", ResourceType = typeof(strings))] | ||||||
|  |         public string DownloadRange { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("liveRecDur", HelpText = "Help_liveRecDur", ResourceType = typeof(strings))] | ||||||
|  |         public string LiveRecDur { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("stopSpeed", HelpText = "Help_stopSpeed", ResourceType = typeof(strings))] | ||||||
|  |         public long StopSpeed { get; set; } = 0L; | ||||||
|  |  | ||||||
|  |         [Option("maxSpeed", HelpText = "Help_maxSpeed", ResourceType = typeof(strings))] | ||||||
|  |         public long MaxSpeed { get; set; } = 0L; | ||||||
|  |  | ||||||
|  |         [Option("proxyAddress", HelpText = "Help_proxyAddress", ResourceType = typeof(strings))] | ||||||
|  |         public string ProxyAddress { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("enableDelAfterDone", HelpText = "Help_enableDelAfterDone", ResourceType = typeof(strings))] | ||||||
|  |         public bool EnableDelAfterDone { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("enableMuxFastStart", HelpText = "Help_enableMuxFastStart", ResourceType = typeof(strings))] | ||||||
|  |         public bool EnableMuxFastStart { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("enableBinaryMerge", HelpText = "Help_enableBinaryMerge", ResourceType = typeof(strings))] | ||||||
|  |         public bool EnableBinaryMerge { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("enableParseOnly", HelpText = "Help_enableParseOnly", ResourceType = typeof(strings))] | ||||||
|  |         public bool EnableParseOnly { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("enableAudioOnly", HelpText = "Help_enableAudioOnly", ResourceType = typeof(strings))] | ||||||
|  |         public bool EnableAudioOnly { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("disableDateInfo", HelpText = "Help_disableDateInfo", ResourceType = typeof(strings))] | ||||||
|  |         public bool DisableDateInfo { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("disableIntegrityCheck", HelpText = "Help_disableIntegrityCheck", ResourceType = typeof(strings))] | ||||||
|  |         public bool DisableIntegrityCheck { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("noMerge", HelpText = "Help_noMerge", ResourceType = typeof(strings))] | ||||||
|  |         public bool NoMerge { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("noProxy", HelpText = "Help_noProxy", ResourceType = typeof(strings))] | ||||||
|  |         public bool NoProxy { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("registerUrlProtocol", HelpText = "Help_registerUrlProtocol", ResourceType = typeof(strings))] | ||||||
|  |         public bool RegisterUrlProtocol { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("unregisterUrlProtocol", HelpText = "Help_unregisterUrlProtocol", ResourceType = typeof(strings))] | ||||||
|  |         public bool UnregisterUrlProtocol { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("enableChaCha20", HelpText = "enableChaCha20")] | ||||||
|  |         public bool EnableChaCha20 { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("chaCha20KeyBase64", HelpText = "ChaCha20KeyBase64")] | ||||||
|  |         public string ChaCha20KeyBase64 { get; set; } | ||||||
|  |  | ||||||
|  |         [Option("chaCha20NonceBase64", HelpText = "ChaCha20NonceBase64")] | ||||||
|  |         public string ChaCha20NonceBase64 { get; set; } | ||||||
|  |  | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										179
									
								
								N_m3u8DL-CLI/N_m3u8DL-CLI.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								N_m3u8DL-CLI/N_m3u8DL-CLI.csproj
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,179 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||||
|  |   <Import Project="..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" /> | ||||||
|  |   <Import Project="..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props" Condition="Exists('..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props')" /> | ||||||
|  |   <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | ||||||
|  |     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | ||||||
|  |     <ProjectGuid>{4FB61439-B738-46AC-B3AF-2BF72150D057}</ProjectGuid> | ||||||
|  |     <OutputType>Exe</OutputType> | ||||||
|  |     <RootNamespace>N_m3u8DL_CLI</RootNamespace> | ||||||
|  |     <AssemblyName>N_m3u8DL-CLI</AssemblyName> | ||||||
|  |     <TargetFrameworkVersion>v4.6</TargetFrameworkVersion> | ||||||
|  |     <FileAlignment>512</FileAlignment> | ||||||
|  |     <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> | ||||||
|  |     <TargetFrameworkProfile /> | ||||||
|  |     <NuGetPackageImportStamp> | ||||||
|  |     </NuGetPackageImportStamp> | ||||||
|  |   </PropertyGroup> | ||||||
|  |   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||||||
|  |     <PlatformTarget>x86</PlatformTarget> | ||||||
|  |     <DebugSymbols>true</DebugSymbols> | ||||||
|  |     <DebugType>full</DebugType> | ||||||
|  |     <Optimize>false</Optimize> | ||||||
|  |     <OutputPath>bin\Debug\</OutputPath> | ||||||
|  |     <DefineConstants>DEBUG;TRACE</DefineConstants> | ||||||
|  |     <ErrorReport>prompt</ErrorReport> | ||||||
|  |     <WarningLevel>4</WarningLevel> | ||||||
|  |     <Prefer32Bit>false</Prefer32Bit> | ||||||
|  |   </PropertyGroup> | ||||||
|  |   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||||||
|  |     <PlatformTarget>AnyCPU</PlatformTarget> | ||||||
|  |     <DebugType>pdbonly</DebugType> | ||||||
|  |     <Optimize>true</Optimize> | ||||||
|  |     <OutputPath>bin\Release\</OutputPath> | ||||||
|  |     <DefineConstants>TRACE</DefineConstants> | ||||||
|  |     <ErrorReport>prompt</ErrorReport> | ||||||
|  |     <WarningLevel>4</WarningLevel> | ||||||
|  |     <Prefer32Bit>false</Prefer32Bit> | ||||||
|  |   </PropertyGroup> | ||||||
|  |   <PropertyGroup> | ||||||
|  |     <ApplicationIcon>logo_3Iv_icon.ico</ApplicationIcon> | ||||||
|  |   </PropertyGroup> | ||||||
|  |   <ItemGroup> | ||||||
|  |     <Reference Include="BrotliSharpLib, Version=0.3.2.0, Culture=neutral, PublicKeyToken=3f4e2a1cd615fcb7, processorArchitecture=MSIL"> | ||||||
|  |       <HintPath>..\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll</HintPath> | ||||||
|  |     </Reference> | ||||||
|  |     <Reference Include="CommandLine, Version=2.8.0.0, Culture=neutral, PublicKeyToken=5a870481e358d379, processorArchitecture=MSIL"> | ||||||
|  |       <HintPath>..\packages\CommandLineParser.2.8.0\lib\net45\CommandLine.dll</HintPath> | ||||||
|  |     </Reference> | ||||||
|  |     <Reference Include="Costura, Version=4.1.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL"> | ||||||
|  |       <HintPath>..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll</HintPath> | ||||||
|  |     </Reference> | ||||||
|  |     <Reference Include="Microsoft.Build.Framework" /> | ||||||
|  |     <Reference Include="Microsoft.Build.Utilities.v4.0" /> | ||||||
|  |     <Reference Include="Microsoft.JScript" /> | ||||||
|  |     <Reference Include="Microsoft.Win32.TaskScheduler, Version=2.8.7.0, Culture=neutral, PublicKeyToken=c416bc1b32d97233, processorArchitecture=MSIL"> | ||||||
|  |       <HintPath>..\packages\TaskScheduler.2.8.7\lib\net452\Microsoft.Win32.TaskScheduler.dll</HintPath> | ||||||
|  |     </Reference> | ||||||
|  |     <Reference Include="MihaZupan.HttpToSocks5Proxy, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL"> | ||||||
|  |       <HintPath>..\packages\HttpToSocks5Proxy.1.4.0\lib\net45\MihaZupan.HttpToSocks5Proxy.dll</HintPath> | ||||||
|  |     </Reference> | ||||||
|  |     <Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" /> | ||||||
|  |     <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | ||||||
|  |       <HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> | ||||||
|  |     </Reference> | ||||||
|  |     <Reference Include="NiL.JS, Version=2.5.1428.0, Culture=neutral, PublicKeyToken=fa941a7c2a4de689, processorArchitecture=MSIL"> | ||||||
|  |       <HintPath>..\packages\NiL.JS.2.5.1428\lib\net45\NiL.JS.dll</HintPath> | ||||||
|  |     </Reference> | ||||||
|  |     <Reference Include="PresentationFramework" /> | ||||||
|  |     <Reference Include="System" /> | ||||||
|  |     <Reference Include="System.Collections" /> | ||||||
|  |     <Reference Include="System.Core" /> | ||||||
|  |     <Reference Include="System.Drawing" /> | ||||||
|  |     <Reference Include="System.IO" /> | ||||||
|  |     <Reference Include="System.IO.Compression" /> | ||||||
|  |     <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | ||||||
|  |       <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath> | ||||||
|  |     </Reference> | ||||||
|  |     <Reference Include="System.Web" /> | ||||||
|  |     <Reference Include="System.Windows.Forms" /> | ||||||
|  |     <Reference Include="System.Xml.Linq" /> | ||||||
|  |     <Reference Include="System.Data.DataSetExtensions" /> | ||||||
|  |     <Reference Include="Microsoft.CSharp" /> | ||||||
|  |     <Reference Include="System.Data" /> | ||||||
|  |     <Reference Include="System.Net.Http" /> | ||||||
|  |     <Reference Include="System.Xml" /> | ||||||
|  |     <Reference Include="UACHelper, Version=1.3.0.4, Culture=neutral, processorArchitecture=MSIL"> | ||||||
|  |       <HintPath>..\packages\UACHelper.1.3.0.5\lib\net40\UACHelper.dll</HintPath> | ||||||
|  |     </Reference> | ||||||
|  |   </ItemGroup> | ||||||
|  |   <ItemGroup> | ||||||
|  |     <Compile Include="CSChaCha20.cs" /> | ||||||
|  |     <Compile Include="Decode51CtoKey.cs" /> | ||||||
|  |     <Compile Include="DecodeCdeledu.cs" /> | ||||||
|  |     <Compile Include="DecodeDdyun.cs" /> | ||||||
|  |     <Compile Include="DecodeHuke88Key.cs" /> | ||||||
|  |     <Compile Include="DecodeImooc.cs" /> | ||||||
|  |     <Compile Include="Decrypter.cs" /> | ||||||
|  |     <Compile Include="DecodeNfmovies.cs" /> | ||||||
|  |     <Compile Include="FFmpeg.cs" /> | ||||||
|  |     <Compile Include="Global.cs" /> | ||||||
|  |     <Compile Include="HLSLiveDownloader.cs" /> | ||||||
|  |     <Compile Include="HLSTags.cs" /> | ||||||
|  |     <Compile Include="IqJsonParser.cs" /> | ||||||
|  |     <Compile Include="LOGGER.cs" /> | ||||||
|  |     <Compile Include="DownloadManager.cs" /> | ||||||
|  |     <Compile Include="MPDParser.cs" /> | ||||||
|  |     <Compile Include="MyOptions.cs" /> | ||||||
|  |     <Compile Include="Parser.cs" /> | ||||||
|  |     <Compile Include="Program.cs" /> | ||||||
|  |     <Compile Include="ProgressReporter.cs" /> | ||||||
|  |     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||||
|  |     <Compile Include="Downloader.cs" /> | ||||||
|  |     <Compile Include="strings.Designer.cs"> | ||||||
|  |       <AutoGen>True</AutoGen> | ||||||
|  |       <DesignTime>True</DesignTime> | ||||||
|  |       <DependentUpon>strings.resx</DependentUpon> | ||||||
|  |     </Compile> | ||||||
|  |     <Compile Include="strings.en-US.Designer.cs"> | ||||||
|  |       <AutoGen>True</AutoGen> | ||||||
|  |       <DesignTime>True</DesignTime> | ||||||
|  |       <DependentUpon>strings.en-US.resx</DependentUpon> | ||||||
|  |     </Compile> | ||||||
|  |     <Compile Include="strings.zh-TW.Designer.cs"> | ||||||
|  |       <AutoGen>True</AutoGen> | ||||||
|  |       <DesignTime>True</DesignTime> | ||||||
|  |       <DependentUpon>strings.zh-TW.resx</DependentUpon> | ||||||
|  |     </Compile> | ||||||
|  |     <Compile Include="Watcher.cs" /> | ||||||
|  |   </ItemGroup> | ||||||
|  |   <ItemGroup> | ||||||
|  |     <None Include="App.config"> | ||||||
|  |       <SubType>Designer</SubType> | ||||||
|  |     </None> | ||||||
|  |     <None Include="packages.config" /> | ||||||
|  |   </ItemGroup> | ||||||
|  |   <ItemGroup> | ||||||
|  |     <COMReference Include="Scripting"> | ||||||
|  |       <Guid>{420B2830-E718-11CF-893D-00A0C9054228}</Guid> | ||||||
|  |       <VersionMajor>1</VersionMajor> | ||||||
|  |       <VersionMinor>0</VersionMinor> | ||||||
|  |       <Lcid>0</Lcid> | ||||||
|  |       <WrapperTool>tlbimp</WrapperTool> | ||||||
|  |       <Isolated>False</Isolated> | ||||||
|  |       <EmbedInteropTypes>True</EmbedInteropTypes> | ||||||
|  |     </COMReference> | ||||||
|  |   </ItemGroup> | ||||||
|  |   <ItemGroup> | ||||||
|  |     <Content Include="logo_3Iv_icon.ico" /> | ||||||
|  |   </ItemGroup> | ||||||
|  |   <ItemGroup> | ||||||
|  |     <EmbeddedResource Include="strings.en-US.resx"> | ||||||
|  |       <Generator>PublicResXFileCodeGenerator</Generator> | ||||||
|  |       <LastGenOutput>strings.en-US.Designer.cs</LastGenOutput> | ||||||
|  |       <SubType>Designer</SubType> | ||||||
|  |     </EmbeddedResource> | ||||||
|  |     <EmbeddedResource Include="strings.resx"> | ||||||
|  |       <Generator>PublicResXFileCodeGenerator</Generator> | ||||||
|  |       <LastGenOutput>strings.Designer.cs</LastGenOutput> | ||||||
|  |       <SubType>Designer</SubType> | ||||||
|  |     </EmbeddedResource> | ||||||
|  |     <EmbeddedResource Include="strings.zh-TW.resx"> | ||||||
|  |       <Generator>PublicResXFileCodeGenerator</Generator> | ||||||
|  |       <LastGenOutput>strings.zh-TW.Designer.cs</LastGenOutput> | ||||||
|  |       <SubType>Designer</SubType> | ||||||
|  |     </EmbeddedResource> | ||||||
|  |   </ItemGroup> | ||||||
|  |   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||||||
|  |   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> | ||||||
|  |     <PropertyGroup> | ||||||
|  |       <ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText> | ||||||
|  |     </PropertyGroup> | ||||||
|  |     <Error Condition="!Exists('..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props'))" /> | ||||||
|  |     <Error Condition="!Exists('..\packages\Fody.6.0.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.6.0.0\build\Fody.targets'))" /> | ||||||
|  |     <Error Condition="!Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" /> | ||||||
|  |   </Target> | ||||||
|  |   <Import Project="..\packages\Fody.6.0.0\build\Fody.targets" Condition="Exists('..\packages\Fody.6.0.0\build\Fody.targets')" /> | ||||||
|  | </Project> | ||||||
							
								
								
									
										1001
									
								
								N_m3u8DL-CLI/Parser.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1001
									
								
								N_m3u8DL-CLI/Parser.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										525
									
								
								N_m3u8DL-CLI/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										525
									
								
								N_m3u8DL-CLI/Program.cs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										39
									
								
								N_m3u8DL-CLI/ProgressReporter.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								N_m3u8DL-CLI/ProgressReporter.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     class ProgressReporter | ||||||
|  |     { | ||||||
|  |         private static string speed = ""; | ||||||
|  |         private static string progress = ""; | ||||||
|  |  | ||||||
|  |         static object lockThis = new object(); | ||||||
|  |         public static void Report(string progress, string speed) | ||||||
|  |         { | ||||||
|  |             lock (lockThis) | ||||||
|  |             { | ||||||
|  |                 int windowWith = 63; | ||||||
|  |                 try | ||||||
|  |                 { | ||||||
|  |                     windowWith = Console.WindowWidth; | ||||||
|  |                 } | ||||||
|  |                 catch (Exception e) | ||||||
|  |                 { | ||||||
|  |                     // empty | ||||||
|  |                 } | ||||||
|  |                 if (!string.IsNullOrEmpty(progress)) ProgressReporter.progress = progress; | ||||||
|  |                 if (!string.IsNullOrEmpty(speed)) ProgressReporter.speed = speed; | ||||||
|  |                 string now = DateTime.Now.ToString("HH:mm:ss.000"); | ||||||
|  |                 var sub = windowWith - 4 - ProgressReporter.progress.Length - ProgressReporter.speed.Length - now.Length; | ||||||
|  |                 if (sub <= 0) sub = 0; | ||||||
|  |                 string print = now + " " + ProgressReporter.progress + " " + ProgressReporter.speed + new string(' ', sub); | ||||||
|  |                 Console.Write("\r" + print + "\r"); | ||||||
|  |                 //Console.Write(print); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								N_m3u8DL-CLI/Properties/AssemblyInfo.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								N_m3u8DL-CLI/Properties/AssemblyInfo.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | using System.Reflection; | ||||||
|  | using System.Runtime.CompilerServices; | ||||||
|  | using System.Runtime.InteropServices; | ||||||
|  |  | ||||||
|  | // 有关程序集的一般信息由以下 | ||||||
|  | // 控制。更改这些特性值可修改 | ||||||
|  | // 与程序集关联的信息。 | ||||||
|  | [assembly: AssemblyTitle("N_m3u8DL-CLI")] | ||||||
|  | [assembly: AssemblyDescription("一款命令行m3u8下载器")] | ||||||
|  | [assembly: AssemblyConfiguration("")] | ||||||
|  | [assembly: AssemblyCompany("nilaoda")] | ||||||
|  | [assembly: AssemblyProduct("N_m3u8DL-CLI")] | ||||||
|  | [assembly: AssemblyCopyright("Copyright ©  2022")] | ||||||
|  | [assembly: AssemblyTrademark("")] | ||||||
|  | [assembly: AssemblyCulture("")] | ||||||
|  |  | ||||||
|  | // 将 ComVisible 设置为 false 会使此程序集中的类型 | ||||||
|  | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 | ||||||
|  | //请将此类型的 ComVisible 特性设置为 true。 | ||||||
|  | [assembly: ComVisible(false)] | ||||||
|  |  | ||||||
|  | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID | ||||||
|  | [assembly: Guid("4fb61439-b738-46ac-b3af-2bf72150d057")] | ||||||
|  |  | ||||||
|  | // 程序集的版本信息由下列四个值组成:  | ||||||
|  | // | ||||||
|  | //      主版本 | ||||||
|  | //      次版本 | ||||||
|  | //      生成号 | ||||||
|  | //      修订号 | ||||||
|  | // | ||||||
|  | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 | ||||||
|  | // 方法是按如下所示使用“*”: : | ||||||
|  | // [assembly: AssemblyVersion("1.0.*")] | ||||||
|  | [assembly: AssemblyVersion("3.0.2.0")] | ||||||
|  | [assembly: AssemblyFileVersion("3.0.2.0")] | ||||||
							
								
								
									
										110
									
								
								N_m3u8DL-CLI/Watcher.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								N_m3u8DL-CLI/Watcher.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | |||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.IO; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Text; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  | using System.Timers; | ||||||
|  |  | ||||||
|  | namespace N_m3u8DL_CLI | ||||||
|  | { | ||||||
|  |     class Watcher | ||||||
|  |     { | ||||||
|  |         private string dir = string.Empty; | ||||||
|  |         private int total = 0; | ||||||
|  |         private static double totalDuration = 0; //总时长 | ||||||
|  |         private int now = 0; | ||||||
|  |         private int partsCount = 0; | ||||||
|  |         FileSystemWatcher watcher = new FileSystemWatcher(); | ||||||
|  |  | ||||||
|  |         public int Total { get => total; set => total = value; } | ||||||
|  |         public int Now { get => now; set => now = value; } | ||||||
|  |         public int PartsCount { get => partsCount; set => partsCount = value; } | ||||||
|  |         public static double TotalDuration { get => totalDuration; set => totalDuration = value; } | ||||||
|  |  | ||||||
|  |         public Watcher(string Dir) | ||||||
|  |         { | ||||||
|  |             this.dir = Dir; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void WatcherStrat() | ||||||
|  |         { | ||||||
|  |             for (int i = 0; i < PartsCount; i++) | ||||||
|  |             { | ||||||
|  |                 Now += Global.GetFileCount(dir + "\\Part_" + i.ToString(DownloadManager.partsPadZero), ".ts"); | ||||||
|  |             } | ||||||
|  |             watcher.Path = dir; | ||||||
|  |             watcher.Filter = "*.ts"; | ||||||
|  |             watcher.IncludeSubdirectories = true;  //包括子目录 | ||||||
|  |             watcher.EnableRaisingEvents = true;    //开启提交事件 | ||||||
|  |             watcher.Created += new FileSystemEventHandler(OnCreated); | ||||||
|  |             watcher.Renamed += new RenamedEventHandler(OnCreated); | ||||||
|  |             watcher.Deleted += new FileSystemEventHandler(OnDeleted); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void WatcherStop() | ||||||
|  |         { | ||||||
|  |             watcher.Dispose(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void OnCreated(object source, FileSystemEventArgs e) | ||||||
|  |         { | ||||||
|  |             if (Path.GetFileNameWithoutExtension(e.FullPath).StartsWith("Part")) | ||||||
|  |                 return; | ||||||
|  |             Now++; | ||||||
|  |             if (Now > Total) | ||||||
|  |             { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             //Console.Title = Now + "   /   " + Total; | ||||||
|  |             string downloadedSize = Global.FormatFileSize(DownloadManager.DownloadedSize); | ||||||
|  |             string estimatedSize = Global.FormatFileSize(DownloadManager.DownloadedSize * total / now); | ||||||
|  |             int padding = downloadedSize.Length > estimatedSize.Length ? downloadedSize.Length : estimatedSize.Length; | ||||||
|  |             DownloadManager.ToDoSize = (DownloadManager.DownloadedSize * total / now) - DownloadManager.DownloadedSize; | ||||||
|  |             string percent = (Convert.ToDouble(now) / Convert.ToDouble(total) * 100).ToString("0.00") + "%"; | ||||||
|  |             var print = "Progress: " + Now + "/" + Total | ||||||
|  |                 + $" ({percent}) -- {downloadedSize.PadLeft(padding)}/{estimatedSize.PadRight(padding)}"; | ||||||
|  |             ProgressReporter.Report(print, ""); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void OnRenamed(object source, RenamedEventArgs e) | ||||||
|  |         { | ||||||
|  |             if (Path.GetFileNameWithoutExtension(e.FullPath).StartsWith("Part")) | ||||||
|  |                 return; | ||||||
|  |             Now++; | ||||||
|  |             if (Now > Total) | ||||||
|  |             { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             //Console.Title = Now + "   /   " + Total; | ||||||
|  |             string downloadedSize = Global.FormatFileSize(DownloadManager.DownloadedSize); | ||||||
|  |             string estimatedSize = Global.FormatFileSize(DownloadManager.DownloadedSize * total / now); | ||||||
|  |             int padding = downloadedSize.Length > estimatedSize.Length ? downloadedSize.Length : estimatedSize.Length; | ||||||
|  |             DownloadManager.ToDoSize = (DownloadManager.DownloadedSize * total / now) - DownloadManager.DownloadedSize; | ||||||
|  |             string percent = (Convert.ToDouble(now) / Convert.ToDouble(total) * 100).ToString("0.00") + "%"; | ||||||
|  |             var print = "Progress: " + Now + "/" + Total | ||||||
|  |                 + $" ({percent}) -- {downloadedSize.PadLeft(padding)}/{estimatedSize.PadRight(padding)}"; | ||||||
|  |             ProgressReporter.Report(print, ""); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void OnDeleted(object source, FileSystemEventArgs e) | ||||||
|  |         { | ||||||
|  |             if (Path.GetFileNameWithoutExtension(e.FullPath).StartsWith("Part")) | ||||||
|  |                 return; | ||||||
|  |             Now--; | ||||||
|  |             if (Now > Total) | ||||||
|  |             { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             //Console.Title = Now + "   /   " + Total; | ||||||
|  |             string downloadedSize = Global.FormatFileSize(DownloadManager.DownloadedSize); | ||||||
|  |             string estimatedSize = Global.FormatFileSize(DownloadManager.DownloadedSize * total / now); | ||||||
|  |             int padding = downloadedSize.Length > estimatedSize.Length ? downloadedSize.Length : estimatedSize.Length; | ||||||
|  |             DownloadManager.ToDoSize = (DownloadManager.DownloadedSize * total / now) - DownloadManager.DownloadedSize; | ||||||
|  |             string percent = (Convert.ToDouble(now) / Convert.ToDouble(total) * 100).ToString("0.00") + "%"; | ||||||
|  |             var print = "Progress: " + Now + "/" + Total | ||||||
|  |                 + $" ({percent}) -- {downloadedSize.PadLeft(padding)}/{estimatedSize.PadRight(padding)}"; | ||||||
|  |             ProgressReporter.Report(print, ""); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										362
									
								
								N_m3u8DL-CLI/changelog.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										362
									
								
								N_m3u8DL-CLI/changelog.txt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								N_m3u8DL-CLI/logo_3Iv_icon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								N_m3u8DL-CLI/logo_3Iv_icon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 25 KiB | 
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user