Compare commits
18 Commits
1.1.1
...
ffmpeg_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62a08e14bb | ||
|
|
422d0827f9 | ||
|
|
546a849aa5 | ||
|
|
e06ff53210 | ||
|
|
18375d3d22 | ||
|
|
5fdee94b38 | ||
|
|
7145f72635 | ||
|
|
4f613ad45c | ||
|
|
1afcef88a0 | ||
|
|
1288d0b3f8 | ||
|
|
2bb5feb647 | ||
|
|
602f772fcf | ||
|
|
887b3ed094 | ||
|
|
49e3290f28 | ||
|
|
5d32d91d7d | ||
|
|
2f1858cde7 | ||
|
|
a98ed223c6 | ||
|
|
575569bd91 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,8 +1,3 @@
|
|||||||
dist/
|
dist/
|
||||||
node_modules/
|
node_modules/
|
||||||
obj/
|
|
||||||
typings/
|
typings/
|
||||||
*.dat
|
|
||||||
*.dll
|
|
||||||
*.suo
|
|
||||||
*.tmp
|
|
||||||
10
.npmignore
10
.npmignore
@@ -1,16 +1,8 @@
|
|||||||
extras/
|
extras/
|
||||||
node_modules/
|
node_modules/
|
||||||
obj/
|
|
||||||
src/
|
src/
|
||||||
typings/
|
typings/
|
||||||
*.dat
|
|
||||||
*.DotSettings
|
|
||||||
*.dll
|
|
||||||
*.map
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.suo
|
|
||||||
*.tmp
|
|
||||||
ts.js
|
ts.js
|
||||||
|
tsconfig.json
|
||||||
tsd.json
|
tsd.json
|
||||||
tslint.json
|
tslint.json
|
||||||
14
README.md
14
README.md
@@ -26,14 +26,14 @@ Use the applicable instructions to install. Is your operating system not listed?
|
|||||||
|
|
||||||
### Debian (Mint, Ubuntu, etc)
|
### Debian (Mint, Ubuntu, etc)
|
||||||
|
|
||||||
1. Run in *Terminal*: `sudo apt-get install nodejs npm mkvtoolnix rtmpdump`
|
1. Run in *Terminal*: `sudo apt-get install nodejs npm mkvtoolnix rtmpdump ffmpeg`
|
||||||
2. Run in *Terminal*: `sudo ln -s /usr/bin/nodejs /usr/bin/node`
|
2. Run in *Terminal*: `sudo ln -s /usr/bin/nodejs /usr/bin/node`
|
||||||
3. Run in *Terminal*: `sudo npm install -g crunchyroll`
|
3. Run in *Terminal*: `sudo npm install -g crunchyroll`
|
||||||
|
|
||||||
### Mac OS X
|
### Mac OS X
|
||||||
|
|
||||||
1. Install *Homebrew* following the instructions at http://brew.sh/
|
1. Install *Homebrew* following the instructions at http://brew.sh/
|
||||||
2. Run in *Terminal*: `brew install node mkvtoolnix rtmpdump`
|
2. Run in *Terminal*: `brew install node mkvtoolnix rtmpdump ffmpeg`
|
||||||
3. Run in *Terminal*: `npm install -g crunchyroll`
|
3. Run in *Terminal*: `npm install -g crunchyroll`
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
@@ -80,9 +80,9 @@ Download *Fairy Tail* to the current work directory:
|
|||||||
|
|
||||||
crunchyroll http://www.crunchyroll.com/fairy-tail
|
crunchyroll http://www.crunchyroll.com/fairy-tail
|
||||||
|
|
||||||
Download *Fairy Tail* to `C:\Manga`:
|
Download *Fairy Tail* to `C:\Anime`:
|
||||||
|
|
||||||
crunchyroll --output C:\Manga http://www.crunchyroll.com/fairy-tail
|
crunchyroll --output C:\Anime http://www.crunchyroll.com/fairy-tail
|
||||||
|
|
||||||
#### Switches
|
#### Switches
|
||||||
|
|
||||||
@@ -112,10 +112,6 @@ Download *Fairy Tail* to `C:\Manga`:
|
|||||||
|
|
||||||
More information will be added at a later point. For now the recommendations are:
|
More information will be added at a later point. For now the recommendations are:
|
||||||
|
|
||||||
* Visual Studio 2013 Update 4 (Core)
|
* Atom with `atom-typescript` and `linter-tslint` (and dependencies).
|
||||||
* NodeJS Tools (Debugging)
|
|
||||||
* TypeScript 1.4 (Language)
|
|
||||||
* ReSharper 9.0+ (Hints/Formatting)
|
|
||||||
* Web Essentials (TSLint)
|
|
||||||
|
|
||||||
Since this project uses TypeScript, compile with `node ts` or `npm install`.
|
Since this project uses TypeScript, compile with `node ts` or `npm install`.
|
||||||
|
|||||||
BIN
bin/ffmpeg.exe
Executable file
BIN
bin/ffmpeg.exe
Executable file
Binary file not shown.
@@ -1,102 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<EnableTypeScript>True</EnableTypeScript>
|
|
||||||
<OutputPath>.</OutputPath>
|
|
||||||
<ProjectGuid>{c5cff68a-d733-4347-83e7-6e5fe58eb0e3}</ProjectGuid>
|
|
||||||
<ProjectHome />
|
|
||||||
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
|
|
||||||
<ProjectView>ShowAllFiles</ProjectView>
|
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
|
||||||
<StartupFile>cli.ts</StartupFile>
|
|
||||||
<TypeScriptModuleKind>CommonJS</TypeScriptModuleKind>
|
|
||||||
<TypeScriptNoImplicitAny>True</TypeScriptNoImplicitAny>
|
|
||||||
<TypeScriptOutDir>dist</TypeScriptOutDir>
|
|
||||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
|
|
||||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
|
||||||
<WorkingDirectory>.</WorkingDirectory>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
|
||||||
<TypeScriptSourceMap>True</TypeScriptSourceMap>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
|
||||||
<TypeScriptGeneratesDeclarations>True</TypeScriptGeneratesDeclarations>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<TypeScriptCompile Include="src\cli.ts" />
|
|
||||||
<TypeScriptCompile Include="src\batch.ts" />
|
|
||||||
<TypeScriptCompile Include="src\episode.ts" />
|
|
||||||
<TypeScriptCompile Include="src\index.ts" />
|
|
||||||
<TypeScriptCompile Include="src\request.ts" />
|
|
||||||
<TypeScriptCompile Include="src\series.ts" />
|
|
||||||
<TypeScriptCompile Include="src\subtitle\decode.ts" />
|
|
||||||
<TypeScriptCompile Include="src\subtitle\formats\ass.ts" />
|
|
||||||
<TypeScriptCompile Include="src\subtitle\formats\index.ts" />
|
|
||||||
<TypeScriptCompile Include="src\subtitle\formats\srt.ts" />
|
|
||||||
<TypeScriptCompile Include="src\subtitle\index.ts" />
|
|
||||||
<TypeScriptCompile Include="src\typings.ts" />
|
|
||||||
<TypeScriptCompile Include="src\video\index.ts" />
|
|
||||||
<TypeScriptCompile Include="src\video\merge.ts" />
|
|
||||||
<TypeScriptCompile Include="src\video\stream.ts" />
|
|
||||||
<TypeScriptCompile Include="typings\big-integer\big-integer.d.ts" />
|
|
||||||
<TypeScriptCompile Include="typings\cheerio\cheerio.d.ts" />
|
|
||||||
<TypeScriptCompile Include="typings\commander\commander.d.ts" />
|
|
||||||
<TypeScriptCompile Include="typings\form-data\form-data.d.ts" />
|
|
||||||
<TypeScriptCompile Include="typings\mkdirp\mkdirp.d.ts" />
|
|
||||||
<TypeScriptCompile Include="typings\node\node.d.ts" />
|
|
||||||
<TypeScriptCompile Include="typings\request\request.d.ts" />
|
|
||||||
<TypeScriptCompile Include="typings\xml2js\xml2js.d.ts" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="src\" />
|
|
||||||
<Folder Include="src\subtitle\" />
|
|
||||||
<Folder Include="src\subtitle\formats\" />
|
|
||||||
<Folder Include="src\video\" />
|
|
||||||
<Folder Include="typings" />
|
|
||||||
<Folder Include="typings\big-integer\" />
|
|
||||||
<Folder Include="typings\cheerio\" />
|
|
||||||
<Folder Include="typings\commander\" />
|
|
||||||
<Folder Include="typings\form-data\" />
|
|
||||||
<Folder Include="typings\mkdirp\" />
|
|
||||||
<Folder Include="typings\node" />
|
|
||||||
<Folder Include="typings\request\" />
|
|
||||||
<Folder Include="typings\xml2js\" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" Condition="False" />
|
|
||||||
<Import Project="$(VSToolsPath)\Node.js Tools\Microsoft.NodejsTools.targets" />
|
|
||||||
<ProjectExtensions>
|
|
||||||
<VisualStudio>
|
|
||||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
|
||||||
<WebProjectProperties>
|
|
||||||
<AutoAssignPort>True</AutoAssignPort>
|
|
||||||
<CustomServerUrl>http://localhost:1337</CustomServerUrl>
|
|
||||||
<DevelopmentServerPort>0</DevelopmentServerPort>
|
|
||||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
|
||||||
<IISUrl>http://localhost:48022/</IISUrl>
|
|
||||||
<NTLMAuthentication>False</NTLMAuthentication>
|
|
||||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
|
||||||
<UseCustomServer>True</UseCustomServer>
|
|
||||||
<UseIIS>False</UseIIS>
|
|
||||||
</WebProjectProperties>
|
|
||||||
</FlavorProperties>
|
|
||||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}" User="">
|
|
||||||
<WebProjectProperties>
|
|
||||||
<AlwaysStartWebServerOnDebug>False</AlwaysStartWebServerOnDebug>
|
|
||||||
<AspNetDebugging>True</AspNetDebugging>
|
|
||||||
<EnableENC>False</EnableENC>
|
|
||||||
<ExternalProgram />
|
|
||||||
<NativeDebugging>False</NativeDebugging>
|
|
||||||
<SilverlightDebugging>False</SilverlightDebugging>
|
|
||||||
<SQLDebugging>False</SQLDebugging>
|
|
||||||
<StartAction>CurrentPage</StartAction>
|
|
||||||
<StartCmdLineArguments />
|
|
||||||
<StartExternalURL />
|
|
||||||
<StartPageUrl />
|
|
||||||
<StartWorkingDirectory />
|
|
||||||
</WebProjectProperties>
|
|
||||||
</FlavorProperties>
|
|
||||||
</VisualStudio>
|
|
||||||
</ProjectExtensions>
|
|
||||||
</Project>
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio 2013
|
|
||||||
VisualStudioVersion = 12.0.31101.0
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "crunchyroll.js", "crunchyroll.js.njsproj", "{C5CFF68A-D733-4347-83E7-6E5FE58EB0E3}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{C5CFF68A-D733-4347-83E7-6E5FE58EB0E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{C5CFF68A-D733-4347-83E7-6E5FE58EB0E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{C5CFF68A-D733-4347-83E7-6E5FE58EB0E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{C5CFF68A-D733-4347-83E7-6E5FE58EB0E3}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
|
||||||
<s:String x:Key="/Default/CodeEditing/Intellisense/CodeCompletion/IntellisenseGloballyEnabled/IntellisenseEnabled/@EntryValue">Disabled</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=DeclarationHides/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=InconsistentNaming/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=NotAllPathsReturnValue/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantQualifier/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
|
||||||
|
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SpecifyVariableTypeExplicitly/@EntryIndexedValue">DO_NOT_SHOW</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeInspection/TypeScriptInspections/Level/@EntryValue">TypeScript14</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=TypeScript/@EntryIndexedValue"><?xml version="1.0" encoding="utf-16"?><Profile name="TypeScript"><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><JsReformatCode>True</JsReformatCode><JsFormatDocComments>True</JsFormatDocComments><JsInsertSemicolon>True</JsInsertSemicolon><RemoveRedundantQualifiersTs>True</RemoveRedundantQualifiersTs><OptimizeImportsTs>True</OptimizeImportsTs><OptimizeReferenceCommentsTs>True</OptimizeReferenceCommentsTs><PublicModifierStyleTs>True</PublicModifierStyleTs><RelativePathStyleTs>True</RelativePathStyleTs><TypeAnnotationStyleTs>True</TypeAnnotationStyleTs></Profile></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeCleanup/SilentCleanupProfile/@EntryValue">TypeScript</s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/FORCE_CONTROL_STATEMENTS_BRACES/@EntryValue">ONLY_FOR_MULTILINE</s:String>
|
|
||||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/KEEP_BLANK_LINES_BETWEEN_DECLARATIONS/@EntryValue">1</s:Int64>
|
|
||||||
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue">1</s:Int64>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/QUOTE_STYLE/@EntryValue">SingleQuoted</s:String>
|
|
||||||
|
|
||||||
|
|
||||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/SPACE_WITHIN_OBJECT_LITERAL_BRACES/@EntryValue">False</s:Boolean>
|
|
||||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/JavaScriptCodeFormatting/STICK_COMMENT/@EntryValue">False</s:Boolean>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCONSTRUCTOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FGLOBAL_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLABEL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FLOCAL_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FOBJECT_005FPROPERTY_005FOF_005FFUNCTION/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FPARAMETER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FCLASS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FENUM_005FMEMBER/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FINTERFACE/@EntryIndexedValue"><Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FINTERFACE_005FFOR_005FJS_005FGLOBAL_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FEXPORTED/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FMODULE_005FLOCAL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPRIVATE_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPROTECTED_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FMEMBER_005FACCESSOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FSTATIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FPUBLIC_005FTYPE_005FMETHOD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=TS_005FTYPE_005FPARAMETER/@EntryIndexedValue"><Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FHTML_005FCONTROL/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FNAME/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/WebNaming/UserRules/=ASP_005FTAG_005FPREFIX/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=NAMESPACE_005FALIAS/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FFIELD/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FRESOURCE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String>
|
|
||||||
<s:Boolean x:Key="/Default/CodeStyle/TypeScriptCodeStyle/ExplicitPublicModifier/@EntryValue">True</s:Boolean>
|
|
||||||
<s:String x:Key="/Default/CodeStyle/TypeScriptCodeStyle/FileReferenceStyle/@EntryValue">RelativeDotSlash</s:String>
|
|
||||||
<s:Boolean x:Key="/Default/CodeStyle/TypeScriptCodeStyle/NoImplicitAny/@EntryValue">True</s:Boolean>
|
|
||||||
|
|
||||||
<s:Boolean x:Key="/Default/CodeStyle/TypeScriptCodeStyle/PreferUsingAliases/@EntryValue">False</s:Boolean>
|
|
||||||
<s:Boolean x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=AAA631615CEE9646AA8766F222F9457C/@KeyIndexDefined">True</s:Boolean>
|
|
||||||
<s:String x:Key="/Default/Environment/InjectedLayers/FileInjectedLayer/=AAA631615CEE9646AA8766F222F9457C/AbsolutePath/@EntryValue">C:\Dropbox\Github\crunchyroll.js\crunchyroll.js.sln.DotSettings</s:String>
|
|
||||||
<s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=FileAAA631615CEE9646AA8766F222F9457C/@KeyIndexDefined">True</s:Boolean>
|
|
||||||
<s:Double x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=FileAAA631615CEE9646AA8766F222F9457C/RelativePriority/@EntryValue">1</s:Double></wpf:ResourceDictionary>
|
|
||||||
24
package.json
24
package.json
@@ -11,26 +11,26 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git://github.com/Deathspike/crunchyroll.js.git"
|
"url": "git://github.com/Deathspike/crunchyroll.js.git"
|
||||||
},
|
},
|
||||||
"version": "1.1.1",
|
"version": "1.1.5",
|
||||||
"bin": {
|
"bin": {
|
||||||
"crunchyroll": "./bin/crunchyroll"
|
"crunchyroll": "./bin/crunchyroll"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"big-integer": "^1.4.3",
|
"big-integer": "1.4.4",
|
||||||
"cheerio": "^0.18.0",
|
"cheerio": "0.18.0",
|
||||||
"commander": "^2.6.0",
|
"commander": "2.6.0",
|
||||||
"mkdirp": "^0.5.0",
|
"mkdirp": "0.5.0",
|
||||||
"request": "^2.53.0",
|
"request": "2.53.0",
|
||||||
"xml2js": "^0.4.4"
|
"xml2js": "0.4.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tsd": "^0.5.7",
|
"tsd": "0.5.7",
|
||||||
"tslint": "^2.1.0",
|
"tslint": "2.3.0-beta",
|
||||||
"typescript": "^1.4.1"
|
"typescript": "1.5.0-beta"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepublish": "npm run tsd && node ts",
|
"prepublish": "npm run tsd && tsc",
|
||||||
"test": "node ts --only-test",
|
"test": "node ts --only-test",
|
||||||
"tsd": "./node_modules/.bin/tsd reinstall --overwrite"
|
"tsd": "tsd reinstall -o -s"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/batch.ts
15
src/batch.ts
@@ -1,15 +1,13 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
export = main;
|
|
||||||
import commander = require('commander');
|
import commander = require('commander');
|
||||||
import fs = require('fs');
|
import fs = require('fs');
|
||||||
import path = require('path');
|
import path = require('path');
|
||||||
import series = require('./series');
|
import series from './series';
|
||||||
import typings = require('./typings');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Streams the batch of series to disk.
|
* Streams the batch of series to disk.
|
||||||
*/
|
*/
|
||||||
function main(args: string[], done: (err?: Error) => void) {
|
export default function(args: string[], done: (err?: Error) => void) {
|
||||||
var config = parse(args);
|
var config = parse(args);
|
||||||
var batchPath = path.join(config.output || process.cwd(), 'CrunchyRoll.txt');
|
var batchPath = path.join(config.output || process.cwd(), 'CrunchyRoll.txt');
|
||||||
tasks(config, batchPath, (err, tasks) => {
|
tasks(config, batchPath, (err, tasks) => {
|
||||||
@@ -41,14 +39,15 @@ function split(value: string): string[] {
|
|||||||
previous = i + 1;
|
previous = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pieces.push(value.substring(previous, i).match(/^"?(.+?)"?$/)[1]);
|
var lastPiece = value.substring(previous, i).match(/^"?(.+?)"?$/);
|
||||||
|
if (lastPiece) pieces.push(lastPiece[1]);
|
||||||
return pieces;
|
return pieces;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the configuration or reads the batch-mode file for tasks.
|
* Parses the configuration or reads the batch-mode file for tasks.
|
||||||
*/
|
*/
|
||||||
function tasks(config: typings.IConfigLine, batchPath: string, done: (err: Error, tasks?: typings.IConfigTask[]) => void) {
|
function tasks(config: IConfigLine, batchPath: string, done: (err: Error, tasks?: IConfigTask[]) => void) {
|
||||||
if (config.args.length) {
|
if (config.args.length) {
|
||||||
return done(null, config.args.map(address => {
|
return done(null, config.args.map(address => {
|
||||||
return {address: address, config: config};
|
return {address: address, config: config};
|
||||||
@@ -58,7 +57,7 @@ function tasks(config: typings.IConfigLine, batchPath: string, done: (err: Error
|
|||||||
if (!exists) return done(null, []);
|
if (!exists) return done(null, []);
|
||||||
fs.readFile(batchPath, 'utf8', (err, data) => {
|
fs.readFile(batchPath, 'utf8', (err, data) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
var map: typings.IConfigTask[] = [];
|
var map: IConfigTask[] = [];
|
||||||
data.split(/\r?\n/).forEach(line => {
|
data.split(/\r?\n/).forEach(line => {
|
||||||
if (/^(\/\/|#)/.test(line)) return;
|
if (/^(\/\/|#)/.test(line)) return;
|
||||||
var lineConfig = parse(process.argv.concat(split(line)));
|
var lineConfig = parse(process.argv.concat(split(line)));
|
||||||
@@ -75,7 +74,7 @@ function tasks(config: typings.IConfigLine, batchPath: string, done: (err: Error
|
|||||||
/**
|
/**
|
||||||
* Parses the arguments and returns a configuration.
|
* Parses the arguments and returns a configuration.
|
||||||
*/
|
*/
|
||||||
function parse(args: string[]): typings.IConfigLine {
|
function parse(args: string[]): IConfigLine {
|
||||||
return new commander.Command().version(require('../package').version)
|
return new commander.Command().version(require('../package').version)
|
||||||
// Authentication
|
// Authentication
|
||||||
.option('-p, --pass <s>', 'The password.')
|
.option('-p, --pass <s>', 'The password.')
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import batch = require('./batch');
|
import batch from './batch';
|
||||||
|
|
||||||
batch(process.argv, (err: any) => {
|
batch(process.argv, (err: any) => {
|
||||||
if (err) console.error(err.stack || err);
|
if (err) console.error(err.stack || err);
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
export = main;
|
|
||||||
import cheerio = require('cheerio');
|
import cheerio = require('cheerio');
|
||||||
import fs = require('fs');
|
import fs = require('fs');
|
||||||
import mkdirp = require('mkdirp');
|
import mkdirp = require('mkdirp');
|
||||||
import request = require('./request');
|
import request = require('./request');
|
||||||
import path = require('path');
|
import path = require('path');
|
||||||
import subtitle = require('./subtitle/index');
|
import subtitle from './subtitle/index';
|
||||||
import typings = require('./typings');
|
import video from './video/index';
|
||||||
import video = require('./video/index');
|
|
||||||
import xml2js = require('xml2js');
|
import xml2js = require('xml2js');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Streams the episode to disk.
|
* Streams the episode to disk.
|
||||||
*/
|
*/
|
||||||
function main(config: typings.IConfig, address: string, done: (err: Error) => void) {
|
export default function(config: IConfig, address: string, done: (err: Error) => void) {
|
||||||
scrapePage(config, address, (err, page) => {
|
scrapePage(config, address, (err, page) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
scrapePlayer(config, address, page.id, (err, player) => {
|
scrapePlayer(config, address, page.id, (err, player) => {
|
||||||
@@ -38,7 +36,7 @@ function complete(message: string, begin: number, done: (err: Error) => void) {
|
|||||||
/**
|
/**
|
||||||
* Downloads the subtitle and video.
|
* Downloads the subtitle and video.
|
||||||
*/
|
*/
|
||||||
function download(config: typings.IConfig, page: typings.IEpisodePage, player: typings.IEpisodePlayer, done: (err: Error) => void) {
|
function download(config: IConfig, page: IEpisodePage, player: IEpisodePlayer, done: (err: Error) => void) {
|
||||||
var series = config.series || page.series;
|
var series = config.series || page.series;
|
||||||
var fileName = name(config, page, series);
|
var fileName = name(config, page, series);
|
||||||
var filePath = path.join(config.output || process.cwd(), series, fileName);
|
var filePath = path.join(config.output || process.cwd(), series, fileName);
|
||||||
@@ -51,7 +49,8 @@ function download(config: typings.IConfig, page: typings.IEpisodePage, player: t
|
|||||||
downloadVideo(config, page, player, filePath, err => {
|
downloadVideo(config, page, player, filePath, err => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
if (config.merge) return complete('Finished ' + fileName, now, done);
|
if (config.merge) return complete('Finished ' + fileName, now, done);
|
||||||
video.merge(config, player.video.file, filePath, err => {
|
var isSubtited = Boolean(player.subtitle);
|
||||||
|
video.merge(config, isSubtited, player.video.file, filePath, player.mode, err => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
complete('Finished ' + fileName, now, done);
|
complete('Finished ' + fileName, now, done);
|
||||||
});
|
});
|
||||||
@@ -63,8 +62,9 @@ function download(config: typings.IConfig, page: typings.IEpisodePage, player: t
|
|||||||
/**
|
/**
|
||||||
* Saves the subtitles to disk.
|
* Saves the subtitles to disk.
|
||||||
*/
|
*/
|
||||||
function downloadSubtitle(config: typings.IConfig, player: typings.IEpisodePlayer, filePath: string, done: (err: Error) => void) {
|
function downloadSubtitle(config: IConfig, player: IEpisodePlayer, filePath: string, done: (err?: Error) => void) {
|
||||||
var enc = player.subtitle;
|
var enc = player.subtitle;
|
||||||
|
if (!enc) return done();
|
||||||
subtitle.decode(enc.id, enc.iv, enc.data, (err, data) => {
|
subtitle.decode(enc.id, enc.iv, enc.data, (err, data) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
var formats = subtitle.formats;
|
var formats = subtitle.formats;
|
||||||
@@ -79,23 +79,24 @@ function downloadSubtitle(config: typings.IConfig, player: typings.IEpisodePlaye
|
|||||||
/**
|
/**
|
||||||
* Streams the video to disk.
|
* Streams the video to disk.
|
||||||
*/
|
*/
|
||||||
function downloadVideo(config: typings.IConfig,
|
function downloadVideo(config: IConfig,
|
||||||
page: typings.IEpisodePage,
|
page: IEpisodePage,
|
||||||
player: typings.IEpisodePlayer,
|
player: IEpisodePlayer,
|
||||||
filePath: string,
|
filePath: string,
|
||||||
done: (err: Error) => void) {
|
done: (err: Error) => void) {
|
||||||
video.stream(
|
video.stream(
|
||||||
player.video.host,
|
player.video.host,
|
||||||
player.video.file,
|
player.video.file,
|
||||||
page.swf,
|
page.swf,
|
||||||
filePath + path.extname(player.video.file),
|
filePath, path.extname(player.video.file),
|
||||||
|
player.video.mode,
|
||||||
done);
|
done);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Names the file based on the config, page, series and tag.
|
* Names the file based on the config, page, series and tag.
|
||||||
*/
|
*/
|
||||||
function name(config: typings.IConfig, page: typings.IEpisodePage, series: string) {
|
function name(config: IConfig, page: IEpisodePage, series: string) {
|
||||||
var episode = (page.episode < 10 ? '0' : '') + page.episode;
|
var episode = (page.episode < 10 ? '0' : '') + page.episode;
|
||||||
var volume = (page.volume < 10 ? '0' : '') + page.volume;
|
var volume = (page.volume < 10 ? '0' : '') + page.volume;
|
||||||
var tag = config.tag || 'CrunchyRoll';
|
var tag = config.tag || 'CrunchyRoll';
|
||||||
@@ -114,14 +115,14 @@ function prefix(value: number|string, length: number) {
|
|||||||
/**
|
/**
|
||||||
* Requests the page data and scrapes the id, episode, series and swf.
|
* Requests the page data and scrapes the id, episode, series and swf.
|
||||||
*/
|
*/
|
||||||
function scrapePage(config: typings.IConfig, address: string, done: (err: Error, page?: typings.IEpisodePage) => void) {
|
function scrapePage(config: IConfig, address: string, done: (err: Error, page?: IEpisodePage) => void) {
|
||||||
var id = parseInt((address.match(/[0-9]+$/) || ['0'])[0], 10);
|
var id = parseInt((address.match(/[0-9]+$/) || ['0'])[0], 10);
|
||||||
if (!id) return done(new Error('Invalid address.'));
|
if (!id) return done(new Error('Invalid address.'));
|
||||||
request.get(config, address, (err, result) => {
|
request.get(config, address, (err, result) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
var $ = cheerio.load(result);
|
var $ = cheerio.load(result);
|
||||||
var swf = /^([^?]+)/.exec($('link[rel=video_src]').attr('href'));
|
var swf = /^([^?]+)/.exec($('link[rel=video_src]').attr('href'));
|
||||||
var regexp = /Watch\s+(.+?)(?:\s+Season\s+([0-9]+))?\s+Episode\s+([0-9]+)/;
|
var regexp = /-\s+(?:Watch\s+)?(.+?)(?:\s+Season\s+([0-9]+))?(?:\s+-)?\s+Episode\s+([0-9]+)/;
|
||||||
var data = regexp.exec($('title').text());
|
var data = regexp.exec($('title').text());
|
||||||
if (!swf || !data) return done(new Error('Invalid page.'));
|
if (!swf || !data) return done(new Error('Invalid page.'));
|
||||||
done(null, {
|
done(null, {
|
||||||
@@ -137,7 +138,7 @@ function scrapePage(config: typings.IConfig, address: string, done: (err: Error,
|
|||||||
/**
|
/**
|
||||||
* Requests the player data and scrapes the subtitle and video data.
|
* Requests the player data and scrapes the subtitle and video data.
|
||||||
*/
|
*/
|
||||||
function scrapePlayer(config: typings.IConfig, address: string, id: number, done: (err: Error, player?: typings.IEpisodePlayer) => void) {
|
function scrapePlayer(config: IConfig, address: string, id: number, done: (err: Error, player?: IEpisodePlayer) => void) {
|
||||||
var url = address.match(/^(https?:\/\/[^\/]+)/);
|
var url = address.match(/^(https?:\/\/[^\/]+)/);
|
||||||
if (!url) return done(new Error('Invalid address.'));
|
if (!url) return done(new Error('Invalid address.'));
|
||||||
request.post(config, {
|
request.post(config, {
|
||||||
@@ -148,16 +149,23 @@ function scrapePlayer(config: typings.IConfig, address: string, id: number, done
|
|||||||
xml2js.parseString(result, {
|
xml2js.parseString(result, {
|
||||||
explicitArray: false,
|
explicitArray: false,
|
||||||
explicitRoot: false
|
explicitRoot: false
|
||||||
}, (err: Error, player: typings.IEpisodePlayerConfig) => {
|
}, (err: Error, player: IEpisodePlayerConfig) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
try {
|
try {
|
||||||
|
var isSubtitled = Boolean(player['default:preload'].subtitle);
|
||||||
|
var streamMode="RTMP";
|
||||||
|
if (player['default:preload'].stream_info.host == "")
|
||||||
|
{
|
||||||
|
streamMode="HLS";
|
||||||
|
}
|
||||||
done(null, {
|
done(null, {
|
||||||
subtitle: {
|
subtitle: isSubtitled ? {
|
||||||
id: parseInt(player['default:preload'].subtitle.$.id, 10),
|
id: parseInt(player['default:preload'].subtitle.$.id, 10),
|
||||||
iv: player['default:preload'].subtitle.iv,
|
iv: player['default:preload'].subtitle.iv,
|
||||||
data: player['default:preload'].subtitle.data
|
data: player['default:preload'].subtitle.data
|
||||||
},
|
} : null,
|
||||||
video: {
|
video: {
|
||||||
|
mode: streamMode;
|
||||||
file: player['default:preload'].stream_info.file,
|
file: player['default:preload'].stream_info.file,
|
||||||
host: player['default:preload'].stream_info.host
|
host: player['default:preload'].stream_info.host
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
export import batch = require('./batch');
|
import batch from './batch';
|
||||||
export import episode = require('./episode');
|
import episode from './episode';
|
||||||
export import series = require('./series');
|
import series from './series';
|
||||||
|
export {batch, episode, series};
|
||||||
|
|||||||
16
src/interface/IConfig.d.ts
vendored
Normal file
16
src/interface/IConfig.d.ts
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
interface IConfig {
|
||||||
|
// Authentication
|
||||||
|
pass?: string;
|
||||||
|
user?: string;
|
||||||
|
// Disables
|
||||||
|
cache?: boolean;
|
||||||
|
merge?: boolean;
|
||||||
|
// Filters
|
||||||
|
episode?: number;
|
||||||
|
volume?: number;
|
||||||
|
// Settings
|
||||||
|
format?: string;
|
||||||
|
output?: string;
|
||||||
|
series?: string;
|
||||||
|
tag?: string;
|
||||||
|
}
|
||||||
3
src/interface/IConfigLine.d.ts
vendored
Normal file
3
src/interface/IConfigLine.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
interface IConfigLine extends IConfig {
|
||||||
|
args: string[];
|
||||||
|
}
|
||||||
4
src/interface/IConfigTask.d.ts
vendored
Normal file
4
src/interface/IConfigTask.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
interface IConfigTask {
|
||||||
|
address: string;
|
||||||
|
config: IConfigLine;
|
||||||
|
}
|
||||||
7
src/interface/IEpisodePage.d.ts
vendored
Normal file
7
src/interface/IEpisodePage.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
interface IEpisodePage {
|
||||||
|
id: number;
|
||||||
|
episode: number;
|
||||||
|
series: string;
|
||||||
|
volume: number;
|
||||||
|
swf: string;
|
||||||
|
}
|
||||||
11
src/interface/IEpisodePlayer.d.ts
vendored
Normal file
11
src/interface/IEpisodePlayer.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
interface IEpisodePlayer {
|
||||||
|
subtitle?: {
|
||||||
|
id: number;
|
||||||
|
iv: string;
|
||||||
|
data: string;
|
||||||
|
};
|
||||||
|
video: {
|
||||||
|
file: string;
|
||||||
|
host: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
15
src/interface/IEpisodePlayerConfig.d.ts
vendored
Normal file
15
src/interface/IEpisodePlayerConfig.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
interface IEpisodePlayerConfig {
|
||||||
|
'default:preload': {
|
||||||
|
subtitle: {
|
||||||
|
$: {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
iv: string;
|
||||||
|
data: string;
|
||||||
|
};
|
||||||
|
stream_info: {
|
||||||
|
file: string;
|
||||||
|
host: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
3
src/interface/IFormatterTable.d.ts
vendored
Normal file
3
src/interface/IFormatterTable.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
interface IFormatterTable {
|
||||||
|
[key: string]: (input: string|Buffer, done: (err: Error, subtitle?: string) => void) => void;
|
||||||
|
}
|
||||||
4
src/interface/ISeries.d.ts
vendored
Normal file
4
src/interface/ISeries.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
interface ISeries {
|
||||||
|
episodes: ISeriesEpisode[];
|
||||||
|
series: string;
|
||||||
|
}
|
||||||
5
src/interface/ISeriesEpisode.d.ts
vendored
Normal file
5
src/interface/ISeriesEpisode.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
interface ISeriesEpisode {
|
||||||
|
address: string;
|
||||||
|
episode: number;
|
||||||
|
volume: number;
|
||||||
|
}
|
||||||
13
src/interface/ISubtitle.d.ts
vendored
Normal file
13
src/interface/ISubtitle.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
interface ISubtitle {
|
||||||
|
$: {
|
||||||
|
title: string;
|
||||||
|
wrap_style: string;
|
||||||
|
play_res_x: string;
|
||||||
|
play_res_y: string;
|
||||||
|
id: string;
|
||||||
|
lang_string: string;
|
||||||
|
created: string;
|
||||||
|
};
|
||||||
|
events: ISubtitleEvent;
|
||||||
|
styles: ISubtitleStyle;
|
||||||
|
}
|
||||||
15
src/interface/ISubtitleEvent.d.ts
vendored
Normal file
15
src/interface/ISubtitleEvent.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
interface ISubtitleEvent {
|
||||||
|
event: {
|
||||||
|
$: {
|
||||||
|
end: string;
|
||||||
|
start: string;
|
||||||
|
style: string;
|
||||||
|
name: string;
|
||||||
|
margin_l: string;
|
||||||
|
margin_r: string;
|
||||||
|
margin_v: string;
|
||||||
|
effect: string;
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
}[];
|
||||||
|
}
|
||||||
29
src/interface/ISubtitleStyle.d.ts
vendored
Normal file
29
src/interface/ISubtitleStyle.d.ts
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
interface ISubtitleStyle {
|
||||||
|
style: {
|
||||||
|
$: {
|
||||||
|
name: string;
|
||||||
|
font_name: string;
|
||||||
|
font_size: string;
|
||||||
|
primary_colour: string;
|
||||||
|
secondary_colour: string;
|
||||||
|
outline_colour: string;
|
||||||
|
back_colour: string;
|
||||||
|
bold: string;
|
||||||
|
italic: string;
|
||||||
|
underline: string;
|
||||||
|
strikeout: string;
|
||||||
|
scale_x: string;
|
||||||
|
scale_y: string;
|
||||||
|
spacing: string;
|
||||||
|
angle: string;
|
||||||
|
border_style: string;
|
||||||
|
outline: string;
|
||||||
|
shadow: string;
|
||||||
|
alignment: string;
|
||||||
|
margin_l: string;
|
||||||
|
margin_r: string;
|
||||||
|
margin_v: string;
|
||||||
|
encoding: string;
|
||||||
|
};
|
||||||
|
}[];
|
||||||
|
}
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import request = require('request');
|
import request = require('request');
|
||||||
import typings = require('./typings');
|
|
||||||
var isAuthenticated = false;
|
var isAuthenticated = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a GET request for the resource.
|
* Performs a GET request for the resource.
|
||||||
*/
|
*/
|
||||||
export function get(config: typings.IConfig, options: request.Options, done: (err: Error, result?: string) => void) {
|
export function get(config: IConfig, options: request.Options, done: (err: Error, result?: string) => void) {
|
||||||
authenticate(config, err => {
|
authenticate(config, err => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
request.get(modify(options), (err: Error, response: any, body: any) => {
|
request.get(modify(options), (err: Error, response: any, body: any) => {
|
||||||
@@ -19,7 +18,7 @@ export function get(config: typings.IConfig, options: request.Options, done: (er
|
|||||||
/**
|
/**
|
||||||
* Performs a POST request for the resource.
|
* Performs a POST request for the resource.
|
||||||
*/
|
*/
|
||||||
export function post(config: typings.IConfig, options: request.Options, done: (err: Error, result?: string) => void) {
|
export function post(config: IConfig, options: request.Options, done: (err: Error, result?: string) => void) {
|
||||||
authenticate(config, err => {
|
authenticate(config, err => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
request.post(modify(options), (err: Error, response: any, body: any) => {
|
request.post(modify(options), (err: Error, response: any, body: any) => {
|
||||||
@@ -32,7 +31,7 @@ export function post(config: typings.IConfig, options: request.Options, done: (e
|
|||||||
/**
|
/**
|
||||||
* Authenticates using the configured pass and user.
|
* Authenticates using the configured pass and user.
|
||||||
*/
|
*/
|
||||||
function authenticate(config: typings.IConfig, done: (err: Error) => void) {
|
function authenticate(config: IConfig, done: (err: Error) => void) {
|
||||||
if (isAuthenticated || !config.pass || !config.user) return done(null);
|
if (isAuthenticated || !config.pass || !config.user) return done(null);
|
||||||
var options = {
|
var options = {
|
||||||
form: {
|
form: {
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
export = main;
|
|
||||||
import cheerio = require('cheerio');
|
import cheerio = require('cheerio');
|
||||||
import episode = require('./episode');
|
import episode from './episode';
|
||||||
import fs = require('fs');
|
import fs = require('fs');
|
||||||
import request = require('./request');
|
import request = require('./request');
|
||||||
import path = require('path');
|
import path = require('path');
|
||||||
import typings = require('./typings');
|
|
||||||
import url = require('url');
|
import url = require('url');
|
||||||
var persistent = '.crpersistent';
|
var persistent = '.crpersistent';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Streams the series to disk.
|
* Streams the series to disk.
|
||||||
*/
|
*/
|
||||||
function main(config: typings.IConfig, address: string, done: (err: Error) => void) {
|
export default function(config: IConfig, address: string, done: (err: Error) => void) {
|
||||||
var persistentPath = path.join(config.output || process.cwd(), persistent);
|
var persistentPath = path.join(config.output || process.cwd(), persistent);
|
||||||
fs.readFile(persistentPath, 'utf8', (err, contents) => {
|
fs.readFile(persistentPath, 'utf8', (err, contents) => {
|
||||||
var cache = config.cache ? {} : JSON.parse(contents || '{}');
|
var cache = config.cache ? {} : JSON.parse(contents || '{}');
|
||||||
@@ -39,9 +37,9 @@ function main(config: typings.IConfig, address: string, done: (err: Error) => vo
|
|||||||
* Downloads the episode.
|
* Downloads the episode.
|
||||||
*/
|
*/
|
||||||
function download(cache: {[address: string]: number},
|
function download(cache: {[address: string]: number},
|
||||||
config: typings.IConfig,
|
config: IConfig,
|
||||||
baseAddress: string,
|
baseAddress: string,
|
||||||
item: typings.ISeriesEpisode,
|
item: ISeriesEpisode,
|
||||||
done: (err: Error) => void) {
|
done: (err: Error) => void) {
|
||||||
if (!filter(config, item)) return done(null);
|
if (!filter(config, item)) return done(null);
|
||||||
var address = url.resolve(baseAddress, item.address);
|
var address = url.resolve(baseAddress, item.address);
|
||||||
@@ -56,7 +54,7 @@ function download(cache: {[address: string]: number},
|
|||||||
/**
|
/**
|
||||||
* Filters the item based on the configuration.
|
* Filters the item based on the configuration.
|
||||||
*/
|
*/
|
||||||
function filter(config: typings.IConfig, item: typings.ISeriesEpisode) {
|
function filter(config: IConfig, item: ISeriesEpisode) {
|
||||||
// Filter on chapter.
|
// Filter on chapter.
|
||||||
var episodeFilter = config.episode;
|
var episodeFilter = config.episode;
|
||||||
if (episodeFilter > 0 && item.episode <= episodeFilter) return false;
|
if (episodeFilter > 0 && item.episode <= episodeFilter) return false;
|
||||||
@@ -72,13 +70,13 @@ function filter(config: typings.IConfig, item: typings.ISeriesEpisode) {
|
|||||||
/**
|
/**
|
||||||
* Requests the page and scrapes the episodes and series.
|
* Requests the page and scrapes the episodes and series.
|
||||||
*/
|
*/
|
||||||
function page(config: typings.IConfig, address: string, done: (err: Error, result?: typings.ISeries) => void) {
|
function page(config: IConfig, address: string, done: (err: Error, result?: ISeries) => void) {
|
||||||
request.get(config, address, (err, result) => {
|
request.get(config, address, (err, result) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
var $ = cheerio.load(result);
|
var $ = cheerio.load(result);
|
||||||
var title = $('span[itemprop=name]').text();
|
var title = $('span[itemprop=name]').text();
|
||||||
if (!title) return done(new Error('Invalid page.'));
|
if (!title) return done(new Error('Invalid page.'));
|
||||||
var episodes: typings.ISeriesEpisode[] = [];
|
var episodes: ISeriesEpisode[] = [];
|
||||||
$('.episode').each((i, el) => {
|
$('.episode').each((i, el) => {
|
||||||
if ($(el).children('img[src*=coming_soon]').length) return;
|
if ($(el).children('img[src*=coming_soon]').length) return;
|
||||||
var volume = /([0-9]+)\s*$/.exec($(el).closest('ul').prev('a').text());
|
var volume = /([0-9]+)\s*$/.exec($(el).closest('ul').prev('a').text());
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
/* tslint:disable:no-bitwise false */
|
/* tslint:disable:no-bitwise false */
|
||||||
'use strict';
|
'use strict';
|
||||||
export = main;
|
|
||||||
import crypto = require('crypto');
|
import crypto = require('crypto');
|
||||||
import bigInt = require('big-integer');
|
import bigInt = require('big-integer');
|
||||||
import zlib = require('zlib');
|
import zlib = require('zlib');
|
||||||
@@ -8,7 +7,7 @@ import zlib = require('zlib');
|
|||||||
/**
|
/**
|
||||||
* Decodes the data.
|
* Decodes the data.
|
||||||
*/
|
*/
|
||||||
function main(id: number, iv: Buffer|string, data: Buffer|string, done: (err?: Error, result?: Buffer) => void) {
|
export default function(id: number, iv: Buffer|string, data: Buffer|string, done: (err?: Error, result?: Buffer) => void) {
|
||||||
try {
|
try {
|
||||||
decompress(decrypt(id, iv, data), done);
|
decompress(decrypt(id, iv, data), done);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
export = main;
|
|
||||||
import xml2js = require('xml2js');
|
import xml2js = require('xml2js');
|
||||||
import typings = require('../../typings');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an input buffer to a SubStation Alpha subtitle.
|
* Converts an input buffer to a SubStation Alpha subtitle.
|
||||||
*/
|
*/
|
||||||
function main(input: string|Buffer, done: (err: Error, subtitle?: string) => void) {
|
export default function(input: string|Buffer, done: (err: Error, subtitle?: string) => void) {
|
||||||
xml2js.parseString(input.toString(), {
|
xml2js.parseString(input.toString(), {
|
||||||
explicitArray: false,
|
explicitArray: false,
|
||||||
explicitRoot: false
|
explicitRoot: false
|
||||||
}, (err: Error, xml: typings.ISubtitle) => {
|
}, (err: Error, xml: ISubtitle) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
try {
|
try {
|
||||||
done(null, script(xml) + '\n' +
|
done(null, script(xml) + '\n' +
|
||||||
@@ -25,11 +23,11 @@ function main(input: string|Buffer, done: (err: Error, subtitle?: string) => voi
|
|||||||
/**
|
/**
|
||||||
* Converts the event block.
|
* Converts the event block.
|
||||||
*/
|
*/
|
||||||
function event(block: typings.ISubtitleEvent): string {
|
function event(block: ISubtitleEvent): string {
|
||||||
var format = 'Layer,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text';
|
var format = 'Layer,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text';
|
||||||
return '[Events]\n' +
|
return '[Events]\n' +
|
||||||
'Format: ' + format + '\n' +
|
'Format: ' + format + '\n' +
|
||||||
block.event.map(style => ('Dialogue: 0,' +
|
[].concat(block.event).map(style => ('Dialogue: 0,' +
|
||||||
style.$.start + ',' +
|
style.$.start + ',' +
|
||||||
style.$.end + ',' +
|
style.$.end + ',' +
|
||||||
style.$.style + ',' +
|
style.$.style + ',' +
|
||||||
@@ -44,7 +42,7 @@ function event(block: typings.ISubtitleEvent): string {
|
|||||||
/**
|
/**
|
||||||
* Converts the script block.
|
* Converts the script block.
|
||||||
*/
|
*/
|
||||||
function script(block: typings.ISubtitle): string {
|
function script(block: ISubtitle): string {
|
||||||
return '[Script Info]\n' +
|
return '[Script Info]\n' +
|
||||||
'Title: ' + block.$.title + '\n' +
|
'Title: ' + block.$.title + '\n' +
|
||||||
'ScriptType: v4.00+\n' +
|
'ScriptType: v4.00+\n' +
|
||||||
@@ -59,14 +57,14 @@ function script(block: typings.ISubtitle): string {
|
|||||||
/**
|
/**
|
||||||
* Converts the style block.
|
* Converts the style block.
|
||||||
*/
|
*/
|
||||||
function style(block: typings.ISubtitleStyle): string {
|
function style(block: ISubtitleStyle): string {
|
||||||
var format = 'Name,Fontname,Fontsize,PrimaryColour,SecondaryColour,' +
|
var format = 'Name,Fontname,Fontsize,PrimaryColour,SecondaryColour,' +
|
||||||
'OutlineColour,BackColour,Bold,Italic,Underline,StrikeOut,ScaleX,' +
|
'OutlineColour,BackColour,Bold,Italic,Underline,StrikeOut,ScaleX,' +
|
||||||
'ScaleY,Spacing,Angle,BorderStyle,Outline,Shadow,Alignment,' +
|
'ScaleY,Spacing,Angle,BorderStyle,Outline,Shadow,Alignment,' +
|
||||||
'MarginL,MarginR,MarginV,Encoding';
|
'MarginL,MarginR,MarginV,Encoding';
|
||||||
return '[V4+ Styles]\n' +
|
return '[V4+ Styles]\n' +
|
||||||
'Format: ' + format + '\n' +
|
'Format: ' + format + '\n' +
|
||||||
block.style.map(style => 'Style: ' +
|
[].concat(block.style).map(style => 'Style: ' +
|
||||||
style.$.name + ',' +
|
style.$.name + ',' +
|
||||||
style.$.font_name + ',' +
|
style.$.font_name + ',' +
|
||||||
style.$.font_size + ',' +
|
style.$.font_size + ',' +
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
export = main;
|
import ass from './ass';
|
||||||
import ass = require('./ass');
|
import srt from './srt';
|
||||||
import srt = require('./srt');
|
|
||||||
import typings = require('../../typings');
|
|
||||||
|
|
||||||
var main: typings.IFormatterTable = {
|
export default <IFormatterTable> {
|
||||||
ass: ass,
|
ass: ass,
|
||||||
srt: srt
|
srt: srt
|
||||||
};
|
};
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
export = srt;
|
|
||||||
import xml2js = require('xml2js');
|
import xml2js = require('xml2js');
|
||||||
import typings = require('../../typings');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an input buffer to a SubRip subtitle.
|
* Converts an input buffer to a SubRip subtitle.
|
||||||
*/
|
*/
|
||||||
function srt(input: Buffer|string, done: (err: Error, subtitle?: string) => void) {
|
export default function(input: Buffer|string, done: (err: Error, subtitle?: string) => void) {
|
||||||
var options = {explicitArray: false, explicitRoot: false};
|
var options = {explicitArray: false, explicitRoot: false};
|
||||||
xml2js.parseString(input.toString(), options, (err: Error, xml: typings.ISubtitle) => {
|
xml2js.parseString(input.toString(), options, (err: Error, xml: ISubtitle) => {
|
||||||
try {
|
try {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
done(null, xml.events.event.map((event, index) => {
|
done(null, xml.events.event.map((event, index) => {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
export import decode = require('./decode');
|
import decode from './decode';
|
||||||
export import formats = require('./formats/index');
|
import formats from './formats/index';
|
||||||
|
export default {decode, formats};
|
||||||
|
|||||||
136
src/typings.ts
136
src/typings.ts
@@ -1,136 +0,0 @@
|
|||||||
export interface IConfig {
|
|
||||||
// Authentication
|
|
||||||
pass?: string;
|
|
||||||
user?: string;
|
|
||||||
// Disables
|
|
||||||
cache?: boolean;
|
|
||||||
merge?: boolean;
|
|
||||||
// Filters
|
|
||||||
episode?: number;
|
|
||||||
volume?: number;
|
|
||||||
// Settings
|
|
||||||
format?: string;
|
|
||||||
output?: string;
|
|
||||||
series?: string;
|
|
||||||
tag?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IConfigLine extends IConfig {
|
|
||||||
args: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IConfigTask {
|
|
||||||
address: string;
|
|
||||||
config: IConfigLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IEpisodePage {
|
|
||||||
id: number;
|
|
||||||
episode: number;
|
|
||||||
series: string;
|
|
||||||
volume: number;
|
|
||||||
swf: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IEpisodePlayer {
|
|
||||||
subtitle: {
|
|
||||||
id: number;
|
|
||||||
iv: string;
|
|
||||||
data: string;
|
|
||||||
};
|
|
||||||
video: {
|
|
||||||
file: string;
|
|
||||||
host: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IEpisodePlayerConfig {
|
|
||||||
'default:preload': {
|
|
||||||
subtitle: {
|
|
||||||
$: {
|
|
||||||
id: string;
|
|
||||||
};
|
|
||||||
iv: string;
|
|
||||||
data: string;
|
|
||||||
};
|
|
||||||
stream_info: {
|
|
||||||
file: string;
|
|
||||||
host: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IFormatterTable {
|
|
||||||
[key: string]: (input: string|Buffer, done: (err: Error, subtitle?: string) => void) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISeries {
|
|
||||||
episodes: ISeriesEpisode[];
|
|
||||||
series: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISeriesEpisode {
|
|
||||||
address: string;
|
|
||||||
episode: number;
|
|
||||||
volume: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISubtitle {
|
|
||||||
$: {
|
|
||||||
title: string;
|
|
||||||
wrap_style: string;
|
|
||||||
play_res_x: string;
|
|
||||||
play_res_y: string;
|
|
||||||
id: string;
|
|
||||||
lang_string: string;
|
|
||||||
created: string;
|
|
||||||
};
|
|
||||||
events: ISubtitleEvent;
|
|
||||||
styles: ISubtitleStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISubtitleEvent {
|
|
||||||
event: {
|
|
||||||
$: {
|
|
||||||
end: string;
|
|
||||||
start: string;
|
|
||||||
style: string;
|
|
||||||
name: string;
|
|
||||||
margin_l: string;
|
|
||||||
margin_r: string;
|
|
||||||
margin_v: string;
|
|
||||||
effect: string;
|
|
||||||
text: string;
|
|
||||||
};
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISubtitleStyle {
|
|
||||||
style: {
|
|
||||||
$: {
|
|
||||||
name: string;
|
|
||||||
font_name: string;
|
|
||||||
font_size: string;
|
|
||||||
primary_colour: string;
|
|
||||||
secondary_colour: string;
|
|
||||||
outline_colour: string;
|
|
||||||
back_colour: string;
|
|
||||||
bold: string;
|
|
||||||
italic: string;
|
|
||||||
underline: string;
|
|
||||||
strikeout: string;
|
|
||||||
scale_x: string;
|
|
||||||
scale_y: string;
|
|
||||||
spacing: string;
|
|
||||||
angle: string;
|
|
||||||
border_style: string;
|
|
||||||
outline: string;
|
|
||||||
shadow: string;
|
|
||||||
alignment: string;
|
|
||||||
margin_l: string;
|
|
||||||
margin_r: string;
|
|
||||||
margin_v: string;
|
|
||||||
encoding: string;
|
|
||||||
};
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
export import merge = require('./merge');
|
import merge from './merge';
|
||||||
export import stream = require('./stream');
|
import stream from './stream';
|
||||||
|
export default {merge, stream};
|
||||||
|
|||||||
@@ -1,22 +1,28 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
export = main;
|
|
||||||
import childProcess = require('child_process');
|
import childProcess = require('child_process');
|
||||||
import fs = require('fs');
|
import fs = require('fs');
|
||||||
import path = require('path');
|
import path = require('path');
|
||||||
import os = require('os');
|
import os = require('os');
|
||||||
import subtitle = require('../subtitle/index');
|
import subtitle from '../subtitle/index';
|
||||||
import typings = require('../typings');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges the subtitle and video files into a Matroska Multimedia Container.
|
* Merges the subtitle and video files into a Matroska Multimedia Container.
|
||||||
*/
|
*/
|
||||||
function main(config: typings.IConfig, rtmpInputPath: string, filePath: string, done: (err: Error) => void) {
|
export default function(config: IConfig, isSubtitled: boolean, rtmpInputPath: string, filePath: string, streamMode: string, done: (err: Error) => void) {
|
||||||
var subtitlePath = filePath + '.' + (subtitle.formats[config.format] ? config.format : 'ass');
|
var subtitlePath = filePath + '.' + (subtitle.formats[config.format] ? config.format : 'ass');
|
||||||
var videoPath = filePath + path.extname(rtmpInputPath);
|
var videoPath = filePath;
|
||||||
|
if (streamMode == "RTMP")
|
||||||
|
{
|
||||||
|
videoPath += path.extname(rtmpInputPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
videoPath += ".mp4";
|
||||||
|
}
|
||||||
childProcess.exec(command() + ' ' +
|
childProcess.exec(command() + ' ' +
|
||||||
'-o "' + filePath + '.mkv" ' +
|
'-o "' + filePath + '.mkv" ' +
|
||||||
'"' + videoPath + '" ' +
|
'"' + videoPath + '" ' +
|
||||||
'"' + subtitlePath + '"', {
|
(isSubtitled ? '"' + subtitlePath + '"' : ''), {
|
||||||
maxBuffer: Infinity
|
maxBuffer: Infinity
|
||||||
}, err => {
|
}, err => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
@@ -32,7 +38,7 @@ function main(config: typings.IConfig, rtmpInputPath: string, filePath: string,
|
|||||||
*/
|
*/
|
||||||
function command(): string {
|
function command(): string {
|
||||||
if (os.platform() !== 'win32') return 'mkvmerge';
|
if (os.platform() !== 'win32') return 'mkvmerge';
|
||||||
return path.join(__dirname, '../../bin/mkvmerge.exe');
|
return '"' + path.join(__dirname, '../../bin/mkvmerge.exe') + '"';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
export = main;
|
|
||||||
import childProcess = require('child_process');
|
import childProcess = require('child_process');
|
||||||
import path = require('path');
|
import path = require('path');
|
||||||
import os = require('os');
|
import os = require('os');
|
||||||
@@ -7,20 +6,38 @@ import os = require('os');
|
|||||||
/**
|
/**
|
||||||
* Streams the video to disk.
|
* Streams the video to disk.
|
||||||
*/
|
*/
|
||||||
function main(rtmpUrl: string, rtmpInputPath: string, swfUrl: string, filePath: string, done: (err: Error) => void) {
|
export default function(rtmpUrl: string, rtmpInputPath: string, swfUrl: string, filePath: string, fileExt: string, mode: string, done: (err: Error) => void) {
|
||||||
childProcess.exec(command() + ' ' +
|
if (mode == "RTMP")
|
||||||
'-r "' + rtmpUrl + '" ' +
|
{
|
||||||
'-y "' + rtmpInputPath + '" ' +
|
childProcess.exec(command("rtmpdump") + ' ' +
|
||||||
'-W "' + swfUrl + '" ' +
|
'-r "' + rtmpUrl + '" ' +
|
||||||
'-o "' + filePath + '"', {
|
'-y "' + rtmpInputPath + '" ' +
|
||||||
maxBuffer: Infinity
|
'-W "' + swfUrl + '" ' +
|
||||||
}, done);
|
'-o "' + filePath + fileExt + '"', {
|
||||||
|
maxBuffer: Infinity
|
||||||
|
}, done);
|
||||||
|
}
|
||||||
|
else if (mode == "HLS")
|
||||||
|
{
|
||||||
|
console.info("Experimental FFMPEG, MAY FAIL!!!");
|
||||||
|
var cmd=command("ffmpeg") + ' ' +
|
||||||
|
'-i "' + rtmpInputPath + '" ' +
|
||||||
|
'-c copy -bsf:a aac_adtstoasc ' +
|
||||||
|
'"' + filePath + '.mp4"';
|
||||||
|
childProcess.exec(cmd, {
|
||||||
|
maxBuffer: Infinity
|
||||||
|
}, done);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.error("No such mode: " + mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the command for the operating system.
|
* Determines the command for the operating system.
|
||||||
*/
|
*/
|
||||||
function command(): string {
|
function command(exe: string): string {
|
||||||
if (os.platform() !== 'win32') return 'rtmpdump';
|
if (os.platform() !== 'win32') return exe;
|
||||||
return path.join(__dirname, '../../bin/rtmpdump.exe');
|
return '"' + path.join(__dirname, '../../bin/' + exe + '.exe') + '"';
|
||||||
}
|
}
|
||||||
24
ts.js
24
ts.js
@@ -4,6 +4,15 @@ var fs = require('fs');
|
|||||||
var path = require('path');
|
var path = require('path');
|
||||||
var isTest = process.argv[2] === '--only-test';
|
var isTest = process.argv[2] === '--only-test';
|
||||||
|
|
||||||
|
// TODO: This build task should be removed upon release of TypeScript 1.5 with
|
||||||
|
// the support for `tsconfig.json`. Invoking `tsc` from `package.json` will then
|
||||||
|
// read the configuration and compile accordingly. It seems that `TSLint` will,
|
||||||
|
// eventually, support this mechanism too. That prevents the need for any kind
|
||||||
|
// of build task and will run entirely based on instructions from `npm`.
|
||||||
|
//
|
||||||
|
// Reference #1: https://github.com/Microsoft/TypeScript/issues/1667
|
||||||
|
// Reference #2: https://github.com/palantir/tslint/issues/281
|
||||||
|
|
||||||
read(function(err, fileNames) {
|
read(function(err, fileNames) {
|
||||||
clean(fileNames, function() {
|
clean(fileNames, function() {
|
||||||
var hasLintError = false;
|
var hasLintError = false;
|
||||||
@@ -50,11 +59,11 @@ function clean(filePaths, done) {
|
|||||||
function compile(filePaths, done) {
|
function compile(filePaths, done) {
|
||||||
if (isTest) return done(null);
|
if (isTest) return done(null);
|
||||||
var execPath = path.join(__dirname, 'node_modules/.bin/tsc');
|
var execPath = path.join(__dirname, 'node_modules/.bin/tsc');
|
||||||
var options = '--declaration --module CommonJS --noImplicitAny --outDir dist';
|
var options = '--declaration --module CommonJS --noImplicitAny --outDir dist --target ES5';
|
||||||
childProcess.exec([execPath, options].concat(filePaths).join(' '), function(err, stdout) {
|
childProcess.exec([execPath, options].concat(filePaths).join(' '), function(err, stdout) {
|
||||||
if (stdout) return done(new Error(stdout));
|
if (stdout) return done(new Error(stdout));
|
||||||
done(null);
|
done(null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,10 +92,5 @@ function lint(filePaths, handler, done) {
|
|||||||
* @param {function(Error, Array.<string>)} done
|
* @param {function(Error, Array.<string>)} done
|
||||||
*/
|
*/
|
||||||
function read(done) {
|
function read(done) {
|
||||||
var contents = fs.readFileSync('crunchyroll.js.njsproj', 'utf8');
|
done(null, JSON.parse(fs.readFileSync('tsconfig.json', 'utf8')).files);
|
||||||
var expression = /<TypeScriptCompile\s+Include="([\w\W]+?\.ts)" \/>/g;
|
|
||||||
var matches;
|
|
||||||
var filePaths = [];
|
|
||||||
while ((matches = expression.exec(contents))) filePaths.push(matches[1]);
|
|
||||||
done(null, filePaths);
|
|
||||||
}
|
}
|
||||||
|
|||||||
52
tsconfig.json
Normal file
52
tsconfig.json
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"version": "1.5.1-beta",
|
||||||
|
"compilerOptions": {
|
||||||
|
"declaration": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"removeComments": false,
|
||||||
|
"module": "commonjs",
|
||||||
|
"outDir": "dist",
|
||||||
|
"sourceMap": true,
|
||||||
|
"target": "es5"
|
||||||
|
},
|
||||||
|
"filesGlob": [
|
||||||
|
"src/**/*.ts",
|
||||||
|
"typings/**/*.ts"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
"src/batch.ts",
|
||||||
|
"src/cli.ts",
|
||||||
|
"src/episode.ts",
|
||||||
|
"src/index.ts",
|
||||||
|
"src/interface/IConfig.d.ts",
|
||||||
|
"src/interface/IConfigLine.d.ts",
|
||||||
|
"src/interface/IConfigTask.d.ts",
|
||||||
|
"src/interface/IEpisodePage.d.ts",
|
||||||
|
"src/interface/IEpisodePlayer.d.ts",
|
||||||
|
"src/interface/IEpisodePlayerConfig.d.ts",
|
||||||
|
"src/interface/IFormatterTable.d.ts",
|
||||||
|
"src/interface/ISeries.d.ts",
|
||||||
|
"src/interface/ISeriesEpisode.d.ts",
|
||||||
|
"src/interface/ISubtitle.d.ts",
|
||||||
|
"src/interface/ISubtitleEvent.d.ts",
|
||||||
|
"src/interface/ISubtitleStyle.d.ts",
|
||||||
|
"src/request.ts",
|
||||||
|
"src/series.ts",
|
||||||
|
"src/subtitle/decode.ts",
|
||||||
|
"src/subtitle/formats/ass.ts",
|
||||||
|
"src/subtitle/formats/index.ts",
|
||||||
|
"src/subtitle/formats/srt.ts",
|
||||||
|
"src/subtitle/index.ts",
|
||||||
|
"src/video/index.ts",
|
||||||
|
"src/video/merge.ts",
|
||||||
|
"src/video/stream.ts",
|
||||||
|
"typings/big-integer/big-integer.d.ts",
|
||||||
|
"typings/cheerio/cheerio.d.ts",
|
||||||
|
"typings/commander/commander.d.ts",
|
||||||
|
"typings/form-data/form-data.d.ts",
|
||||||
|
"typings/mkdirp/mkdirp.d.ts",
|
||||||
|
"typings/node/node.d.ts",
|
||||||
|
"typings/request/request.d.ts",
|
||||||
|
"typings/xml2js/xml2js.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user