diff --git a/bilibili.xcodeproj/project.pbxproj b/bilibili.xcodeproj/project.pbxproj index 5374625..7ea0a08 100644 --- a/bilibili.xcodeproj/project.pbxproj +++ b/bilibili.xcodeproj/project.pbxproj @@ -16,6 +16,8 @@ FD2BD5631AD11319001A7E16 /* playLocalFile.m in Sources */ = {isa = PBXBuildFile; fileRef = FD2BD5621AD11319001A7E16 /* playLocalFile.m */; }; FD2BD56E1AD15AE0001A7E16 /* libmediainfo.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FD2BD56D1AD15AE0001A7E16 /* libmediainfo.0.dylib */; }; FD2BD56F1AD15AF9001A7E16 /* libmediainfo.0.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD2BD56D1AD15AE0001A7E16 /* libmediainfo.0.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + FD33F5B91B085D3100DF4C78 /* LiveChat.m in Sources */ = {isa = PBXBuildFile; fileRef = FD33F5B81B085D3100DF4C78 /* LiveChat.m */; }; + FD33F5C61B08A5A500DF4C78 /* Socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD33F5C41B08A5A500DF4C78 /* Socket.cpp */; }; FD471B4F1AC8FF3C00A2A727 /* PlayerView.mm in Sources */ = {isa = PBXBuildFile; fileRef = FD471B4D1AC8FF3C00A2A727 /* PlayerView.mm */; }; FD471B521AC904CB00A2A727 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FD471B511AC904CB00A2A727 /* CoreAudio.framework */; }; FD476C6A1AD2086900584EFE /* Settings.m in Sources */ = {isa = PBXBuildFile; fileRef = FD476C691AD2086900584EFE /* Settings.m */; }; @@ -76,6 +78,7 @@ FD6102621AD7CC020013119A /* inject.js in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD61025B1AD7CBA20013119A /* inject.js */; }; FD6102631AD7CC020013119A /* webui.html in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD61025D1AD7CBC10013119A /* webui.html */; }; FD6102641AD7CC020013119A /* webui.css in CopyFiles */ = {isa = PBXBuildFile; fileRef = FD6102601AD7CBF10013119A /* webui.css */; }; + FD855FB01B07D884004A1610 /* BilibiliSocketClient.mm in Sources */ = {isa = PBXBuildFile; fileRef = FD855FAF1B07D884004A1610 /* BilibiliSocketClient.mm */; }; FD8CEDEF1AD2499B0092452F /* CommentBlockSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = FD8CEDEE1AD2499B0092452F /* CommentBlockSettings.m */; }; FD8CEDF21AD24A290092452F /* KeywordBlockSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = FD8CEDF11AD24A290092452F /* KeywordBlockSettings.m */; }; FDA775DE1AD93D1800426483 /* libaria2.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FDA775DD1AD93D1800426483 /* libaria2.0.dylib */; }; @@ -188,6 +191,11 @@ FD2BD5621AD11319001A7E16 /* playLocalFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = playLocalFile.m; sourceTree = ""; }; FD2BD56D1AD15AE0001A7E16 /* libmediainfo.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libmediainfo.0.dylib; path = bilibili/libs/libmediainfo.0.dylib; sourceTree = ""; }; FD2BD5701AD15BCA001A7E16 /* MediaInfoDLL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MediaInfoDLL.h; path = bilibili/headers/MediaInfoDLL/MediaInfoDLL.h; sourceTree = ""; }; + FD33F5B31B085BEC00DF4C78 /* BilibiliSocketClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BilibiliSocketClient.h; sourceTree = ""; }; + FD33F5B71B085D3100DF4C78 /* LiveChat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiveChat.h; sourceTree = ""; }; + FD33F5B81B085D3100DF4C78 /* LiveChat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LiveChat.m; sourceTree = ""; }; + FD33F5C41B08A5A500DF4C78 /* Socket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Socket.cpp; sourceTree = ""; }; + FD33F5C51B08A5A500DF4C78 /* Socket.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Socket.hpp; sourceTree = ""; }; FD471B4C1AC8FF3C00A2A727 /* PlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayerView.h; sourceTree = ""; }; FD471B4D1AC8FF3C00A2A727 /* PlayerView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlayerView.mm; sourceTree = ""; }; FD471B511AC904CB00A2A727 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; @@ -227,6 +235,7 @@ FD61025B1AD7CBA20013119A /* inject.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = inject.js; path = WebPages/inject.js; sourceTree = ""; }; FD61025D1AD7CBC10013119A /* webui.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = webui.html; path = WebPages/webui.html; sourceTree = ""; }; FD6102601AD7CBF10013119A /* webui.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = webui.css; path = WebPages/webui.css; sourceTree = ""; }; + FD855FAF1B07D884004A1610 /* BilibiliSocketClient.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BilibiliSocketClient.mm; sourceTree = ""; }; FD8CEDED1AD2499B0092452F /* CommentBlockSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommentBlockSettings.h; sourceTree = ""; }; FD8CEDEE1AD2499B0092452F /* CommentBlockSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CommentBlockSettings.m; sourceTree = ""; }; FD8CEDF01AD24A290092452F /* KeywordBlockSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeywordBlockSettings.h; sourceTree = ""; }; @@ -326,6 +335,7 @@ FD076C521AC8CBBB00C893FA /* bilibili */ = { isa = PBXGroup; children = ( + FD855FAE1B07D86C004A1610 /* RealTimeComments */, FDA775E81AD93ED600426483 /* downloadManager */, FD61025A1AD7CB760013119A /* WebPages */, FD476C701AD22AEC00584EFE /* GUI */, @@ -477,6 +487,8 @@ FD471B4D1AC8FF3C00A2A727 /* PlayerView.mm */, FD4D376C1ACEFD7B0022ABF3 /* PostComment.h */, FD4D376D1ACEFD7B0022ABF3 /* PostComment.m */, + FD33F5B71B085D3100DF4C78 /* LiveChat.h */, + FD33F5B81B085D3100DF4C78 /* LiveChat.m */, ); name = "Player View"; sourceTree = ""; @@ -508,6 +520,17 @@ name = WebPages; sourceTree = ""; }; + FD855FAE1B07D86C004A1610 /* RealTimeComments */ = { + isa = PBXGroup; + children = ( + FD33F5B31B085BEC00DF4C78 /* BilibiliSocketClient.h */, + FD855FAF1B07D884004A1610 /* BilibiliSocketClient.mm */, + FD33F5C41B08A5A500DF4C78 /* Socket.cpp */, + FD33F5C51B08A5A500DF4C78 /* Socket.hpp */, + ); + name = RealTimeComments; + sourceTree = ""; + }; FD8CEDEC1AD249540092452F /* Settings View */ = { isa = PBXGroup; children = ( @@ -694,6 +717,7 @@ buildActionMask = 2147483647; files = ( FD076C5C1AC8CBBB00C893FA /* ViewController.mm in Sources */, + FD855FB01B07D884004A1610 /* BilibiliSocketClient.mm in Sources */, FD076C591AC8CBBB00C893FA /* main.m in Sources */, FD8CEDF21AD24A290092452F /* KeywordBlockSettings.m in Sources */, FD476C6A1AD2086900584EFE /* Settings.m in Sources */, @@ -701,12 +725,14 @@ FD2BD5631AD11319001A7E16 /* playLocalFile.m in Sources */, FDFC8AB91AD5745B000AFDB2 /* danmaku2ass.cpp in Sources */, FD4D376E1ACEFD7B0022ABF3 /* PostComment.m in Sources */, + FD33F5B91B085D3100DF4C78 /* LiveChat.m in Sources */, FDA775E61AD93ECA00426483 /* DownloadManager.m in Sources */, FDFC8AB81AD5745B000AFDB2 /* AssClass.cpp in Sources */, FD471B4F1AC8FF3C00A2A727 /* PlayerView.mm in Sources */, FDAF8BAA1ACA5A3100C0C55D /* AboutView.m in Sources */, FDAF8B9E1ACA4C1C00C0C55D /* ISSoundAdditions.m in Sources */, FD8CEDEF1AD2499B0092452F /* CommentBlockSettings.m in Sources */, + FD33F5C61B08A5A500DF4C78 /* Socket.cpp in Sources */, FD476C731AD22B1F00584EFE /* CommentFilter.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/bilibili/Base.lproj/Main.storyboard b/bilibili/Base.lproj/Main.storyboard index 3f8568b..f7817f0 100644 --- a/bilibili/Base.lproj/Main.storyboard +++ b/bilibili/Base.lproj/Main.storyboard @@ -613,6 +613,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bilibili/BilibiliSocketClient.h b/bilibili/BilibiliSocketClient.h new file mode 100644 index 0000000..15fab31 --- /dev/null +++ b/bilibili/BilibiliSocketClient.h @@ -0,0 +1,20 @@ +// +// BilibiliSocketClient.h +// bilibili +// +// Created by TYPCN on 2015/5/17. +// Copyright (c) 2015 TYPCN. All rights reserved. +// + +#ifndef bilibili_BilibiliSocketClient_h +#define bilibili_BilibiliSocketClient_h + +#import + +@interface LiveSocket : NSObject + +- (bool)ConnectToTheFuckingFlashSocketServer: (int)roomid; + +@end + +#endif diff --git a/bilibili/BilibiliSocketClient.mm b/bilibili/BilibiliSocketClient.mm new file mode 100644 index 0000000..5c432d0 --- /dev/null +++ b/bilibili/BilibiliSocketClient.mm @@ -0,0 +1,52 @@ +// +// SocketClient.m +// bilibili +// +// Created by TYPCN on 2015/5/17. +// Copyright (c) 2015 TYPCN. All rights reserved. +// + +#import "BilibiliSocketClient.h" + +#include "Socket.hpp" + +@implementation LiveSocket{ + tcp_client c; +} + +- (bool)ConnectToTheFuckingFlashSocketServer: (int)roomid{ + if(!c.conn("livecmt.bilibili.com" , 88)){ + return false; + } + + NSString *initStr = [NSString stringWithFormat:@"0101000c0000%04x00000000",roomid]; + NSData *data = [self dataFromHexString:initStr]; + c.send_data([data bytes], (int)[data length]); + while(true){ + std::string str = c.receive(1024); + if(str.length() > 0){ + NSLog(@"Data: %s",str.c_str()); + } + } + return true; +} + +- (NSData *)dataFromHexString:(NSString *)str { + const char *chars = [str UTF8String]; + int i = 0, len = (int)str.length; + + NSMutableData *data = [NSMutableData dataWithCapacity:len / 2]; + char byteChars[3] = {'\0','\0','\0'}; + unsigned long wholeByte; + + while (i < len) { + byteChars[0] = chars[i++]; + byteChars[1] = chars[i++]; + wholeByte = strtoul(byteChars, NULL, 16); + [data appendBytes:&wholeByte length:1]; + } + + return data; +} + +@end diff --git a/bilibili/LiveChat.h b/bilibili/LiveChat.h new file mode 100644 index 0000000..c96caa8 --- /dev/null +++ b/bilibili/LiveChat.h @@ -0,0 +1,13 @@ +// +// LiveChat.h +// bilibili +// +// Created by TYPCN on 2015/5/17. +// Copyright (c) 2015 TYPCN. All rights reserved. +// + +#import + +@interface LiveChat : NSViewController + +@end diff --git a/bilibili/LiveChat.m b/bilibili/LiveChat.m new file mode 100644 index 0000000..d9b72ac --- /dev/null +++ b/bilibili/LiveChat.m @@ -0,0 +1,27 @@ +// +// LiveChat.m +// bilibili +// +// Created by TYPCN on 2015/5/17. +// Copyright (c) 2015 TYPCN. All rights reserved. +// + +#import "LiveChat.h" +#import "BilibiliSocketClient.h" + +extern NSString *vCID; + +@interface LiveChat () + +@end + +@implementation LiveChat + +- (void)viewDidLoad { + [super viewDidLoad]; + LiveSocket *socket = [[LiveSocket alloc] init]; + + [socket ConnectToTheFuckingFlashSocketServer:[vCID intValue]]; +} + +@end diff --git a/bilibili/Socket.cpp b/bilibili/Socket.cpp new file mode 100644 index 0000000..155807d --- /dev/null +++ b/bilibili/Socket.cpp @@ -0,0 +1,128 @@ +// +// Socket.cpp +// bilibili +// +// Created by TYPCN on 2015/5/17. +// Copyright (c) 2015 TYPCN. All rights reserved. +// + +#include "Socket.hpp" + +#include //cout +#include //printf +#include //strlen +#include //string +#include //socket +#include //hostent + +using namespace std; + +tcp_client::tcp_client() +{ + sock = -1; + port = 0; + address = ""; +} + +/** + Connect to a host on a certain port number + */ +bool tcp_client::conn(string address , int port) +{ + //create socket if it is not already created + if(sock == -1) + { + //Create socket + sock = socket(AF_INET , SOCK_STREAM , 0); + if (sock == -1) + { + perror("Could not create socket"); + } + + cout<<"Socket created\n"; + } + else { /* OK , nothing */ } + + //setup address structure + if(inet_addr(address.c_str()) == -1) + { + struct hostent *he; + struct in_addr **addr_list; + + //resolve the hostname, its not an ip address + if ( (he = gethostbyname( address.c_str() ) ) == NULL) + { + //gethostbyname failed + herror("gethostbyname"); + cout<<"Failed to resolve hostname\n"; + + return false; + } + + //Cast the h_addr_list to in_addr , since h_addr_list also has the ip address in long format only + addr_list = (struct in_addr **) he->h_addr_list; + + for(int i = 0; addr_list[i] != NULL; i++) + { + //strcpy(ip , inet_ntoa(*addr_list[i]) ); + server.sin_addr = *addr_list[i]; + + cout< +#include +#include + +class tcp_client{ +private: + int sock; + std::string address; + int port; + struct sockaddr_in server; + +public: + tcp_client(); + bool conn(std::string, int); + bool send_data(const void *data,int size); + std::string receive(int); +}; + +#endif /* defined(__bilibili__Socket__) */ diff --git a/bilibili/ViewController.mm b/bilibili/ViewController.mm index f98ac12..c3c58fc 100644 --- a/bilibili/ViewController.mm +++ b/bilibili/ViewController.mm @@ -356,6 +356,38 @@ - (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame } +- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems{ + NSMenuItem *copy = [[NSMenuItem alloc] initWithTitle:@"复制页面地址" action:@selector(CopyLink) keyEquivalent:@""]; + [copy setTarget:self]; + [copy setEnabled:YES]; + NSMenuItem *play = [[NSMenuItem alloc] initWithTitle:@"强制显示播放界面" action:@selector(ShowPlayer) keyEquivalent:@""]; + [play setTarget:self]; + [play setEnabled:YES]; + NSMenuItem *contact = [[NSMenuItem alloc] initWithTitle:@"呼叫程序猿" action:@selector(Contact) keyEquivalent:@""]; + [contact setTarget:self]; + [contact setEnabled:YES]; + NSMutableArray *mutableArray = [[NSMutableArray alloc] init]; + [mutableArray addObjectsFromArray:defaultMenuItems]; + [mutableArray addObject:copy]; + [mutableArray addObject:play]; + [mutableArray addObject:contact]; + return mutableArray; +} + +- (void)CopyLink{ + [[NSPasteboard generalPasteboard] clearContents]; + [[NSPasteboard generalPasteboard] setString:webView.mainFrameURL forType:NSStringPboardType]; +} + +- (void)ShowPlayer{ + [webView stringByEvaluatingJavaScriptFromString:WebScript]; + userAgent = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]; +} + +- (void)Contact{ + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"mailto:typcncom@gmail.com"]]; +} + - (IBAction)openAv:(id)sender { NSString *avNumber = [sender stringValue]; if([[sender stringValue] length] > 2 ){ diff --git a/bilibiliTests/bilibiliTests.m b/bilibiliTests/bilibiliTests.m index fe03467..e5dc10d 100644 --- a/bilibiliTests/bilibiliTests.m +++ b/bilibiliTests/bilibiliTests.m @@ -9,6 +9,7 @@ #import #import #import "PlayerView.h" +#import "LiveChat.h" #import "CommentFilter.h" extern NSString *vCID; @@ -57,5 +58,15 @@ - (void)testVideoPlayback { }]; } +- (void)testLiveChat { + vCID = @"1029"; + XCTestExpectation *videoPlayExpectation = [self expectationWithDescription:@"Video Playing"]; + NSStoryboard *storyBoard = [NSStoryboard storyboardWithName:@"Main" bundle:nil]; // get a reference to the storyboard + NSWindowController *myController = [storyBoard instantiateControllerWithIdentifier:@"LiveChatWindow"]; // instantiate your window controller + [myController showWindow:self]; // show the window + [self waitForExpectationsWithTimeout:30 handler:^(NSError *error) { + + }]; +} @end