1+ //
2+ // Created by Larry Tin on 2017/6/11.
3+ //
4+
5+ #import " GDCFirebaseChannel.h"
6+ #import " Firebase.h"
7+ #import " GDCBusProvider.h"
8+ #import " GDCMessageImpl.h"
9+ #import " NSObject+GDChannel.h"
10+
11+ @interface GDCFirebaseChannel ()
12+ @property NSString *clientId;
13+ @property FIRDatabaseReference *bufRef;
14+ @property NSMutableDictionary <NSString *, NSString *> *replyTopics;
15+ @end
16+
17+ @implementation GDCFirebaseChannel {
18+
19+ }
20+ - (instancetype )initWithClientId : (NSString *)clientId {
21+ self = [super init ];
22+ if (self) {
23+ _clientId = clientId;
24+ _bufRef = [FIRDatabase.database referenceWithPath: @" bus" ];
25+ _replyTopics = @{}.mutableCopy ;
26+
27+ __weak GDCFirebaseChannel *weakSelf = self;
28+ [[[_bufRef child: @" queue" ] child: clientId] observeEventType: FIRDataEventTypeChildAdded withBlock: ^(FIRDataSnapshot *snapshot) {
29+ NSDictionary *msg = snapshot.value [@" send" ];
30+ NSString *topic = [clientId stringByAppendingPathComponent: msg[@" topic" ]];
31+ id payload = msg[payloadKey];
32+ GDCOptions *options = [GDCOptions parseFromJson: msg[optionsKey] error: nil ];
33+ [weakSelf.bus sendLocal: topic payload: payload options: options replyHandler: ^(id <GDCAsyncResult> asyncResult) {
34+ GDCMessageImpl *msg = asyncResult.result ;
35+ NSDictionary *reply = [msg toJsonWithTopic: NO ];
36+ [[snapshot.ref child: @" reply" ] setValue: reply];
37+ [snapshot.ref onDisconnectRemoveValue ];
38+ }];
39+ }];
40+ }
41+
42+ return self;
43+ }
44+
45+ - (void )goOnline : (id )clientInfo {
46+ [FIRDatabase.database goOnline ];
47+ self.bufRef = [[FIRDatabase.database reference ] child: @" bus" ];
48+ FIRDatabaseReference *clientIdRef = [[self .bufRef child: @" clients" ] child: self .clientId];
49+ [clientIdRef onDisconnectRemoveValueWithCompletionBlock: ^(NSError *error, FIRDatabaseReference *ref) {
50+ if (error) {
51+ return ;
52+ }
53+ [clientIdRef setValue: clientInfo];
54+ }];
55+ }
56+
57+ - (void )reportMessage : (GDCMessageImpl *)message {
58+ if (message.payload && (
59+ ![message.payload conformsToProtocol: @protocol (GDCSerializable)] && ![message.payload isKindOfClass: NSString .class] &&
60+ ![message.payload isKindOfClass: NSNumber .class] && ![message.payload isKindOfClass: NSArray .class] && ![message.payload isKindOfClass: NSDictionary .class])) {
61+ return ;
62+ }
63+ NSString *topic = message.topic ;
64+ NSString *historyPath = nil ;
65+ if ([topic hasPrefix: @" reply/" ]) {
66+ if (!self.replyTopics [topic]) {
67+ return ;
68+ }
69+ historyPath = self.replyTopics [topic];
70+ [self .replyTopics removeObjectForKey: topic];
71+ NSMutableDictionary *value = [message toJsonWithTopic: NO ];
72+ value[@" topic" ] = nil ;
73+ [[[self .bufRef child: historyPath] child: @" reply" ] setValue: value];
74+ return ;
75+ }
76+ if ([topic hasPrefix: [GDCBusProvider.clientId stringByAppendingString: @" /" ]]) {
77+ topic = [topic substringFromIndex: GDCBusProvider.clientId.length + 1 ];
78+ }
79+ historyPath = [NSString stringWithFormat: @" history/%@ /messages/" , [topic stringByReplacingOccurrencesOfString: @" /" withString: @" _" ]];
80+ FIRDatabaseReference *historyRef = [self .bufRef child: historyPath].childByAutoId ;
81+ historyPath = [historyPath stringByAppendingPathComponent: historyRef.key];
82+ if (message.replyTopic ) {
83+ self.replyTopics [message.replyTopic] = historyPath;
84+ }
85+ NSMutableDictionary *msg = @{}.mutableCopy ;
86+ msg[@" client" ] = self.clientId ;
87+ msg[@" send" ] = [message toJsonWithTopic: NO ];
88+ msg[@" send" ][@" topic" ] = topic;
89+ msg[@" send" ][@" replyTopic" ] = nil ;
90+
91+ NSMutableDictionary *values = @{}.mutableCopy ;
92+ values[historyPath] = msg;
93+
94+ NSString *categoryPath = @" category" ;
95+ NSMutableDictionary *categoryValue = @{}.mutableCopy ;
96+ NSRange range = [topic rangeOfString: @" /" ];
97+ NSUInteger index = range.location ;
98+ if (index != NSNotFound ) {
99+ categoryPath = [NSString stringWithFormat: @" %@ /%@ /topics/%@ " , categoryPath, [topic substringToIndex: index],
100+ [[topic substringFromIndex: index + 1 ] stringByReplacingOccurrencesOfString: @" /" withString: @" _" ]];
101+ } else {
102+ categoryPath = [categoryPath stringByAppendingPathComponent: topic];
103+ }
104+ categoryValue[@" version" ] = [[NSBundle mainBundle ] objectForInfoDictionaryKey: @" CFBundleShortVersionString" ];
105+ values[categoryPath] = categoryValue;
106+
107+ [self .bufRef updateChildValues: values];
108+ }
109+ @end
0 commit comments