Skip to content

Instantly share code, notes, and snippets.

@aoberoi
Created December 18, 2012 16:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aoberoi/4329703 to your computer and use it in GitHub Desktop.
Save aoberoi/4329703 to your computer and use it in GitHub Desktop.
# Directory layout:
#
# Broadcasts/
# |- parse/
# |- cloud/
# |- config/
# |- iOS/ <----- downloaded code goes in here
# |- Broadcasts.xcodeproj/
# |- ...
# Directory layout:
#
# Broadcasts/
# |- parse/
# |- cloud/
# |- main.js <----- our functions go here
# |- opentok/ <----- repository copied here
# |- opentok.js
# |- ...
# |- config/
# |- global.json
@implementation BroadcastsAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Parse initialization
[Parse setApplicationId:kParseAppId clientKey:kParseClientKey];
[PFUser enableAutomaticUser];
[[PFUser currentUser] saveInBackground];
PFACL *defaultACL = [PFACL ACL];
//...
}
//...
@end
@implementation BroadcastCreationViewController
//...
- (IBAction)done:(id)sender {
if (self.titleField.text.length > 0 && self.titleField.text.length < 25) {
// Create the new Broadcast object
PFObject *newBroadcast = [PFObject objectWithClassName:@"Broadcast"];
newBroadcast[@"title"] = self.titleField.text;
newBroadcast[@"owner"] = [PFUser currentUser];
// Set the access control for the new Broadcast
PFACL *acl = [PFACL ACLWithUser:[PFUser currentUser]];
[acl setPublicReadAccess:YES];
newBroadcast.ACL = acl;
// Save the new Broadcast
// ...
}
// ...
}
@end
@implementation BroadcastTableViewController
// ...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
// ...
cell.dateLabel.text = [NSDateFormatter localizedStringFromDate:object.createdAt
dateStyle:NSDateFormatterMediumStyle
timeStyle:NSDateFormatterShortStyle];
cell.ownerLabel.hidden = ![[(PFUser *)object[@"owner"] objectId] isEqual:[[PFUser currentUser] objectId]];;
return cell;
}
// ...
@end
# Move to parse directory
$ cd ~/projects/Broadcasts/parse
# Deploy
$ parse deploy
Uploading source files
Finished uploading files
New release is named v1
@implementation BroadcastViewController
// ...
- (void)connectToBroadcast
{
// ...
// Connect to the Session as long as its not already connecting or connected
if ( !( self.session.sessionConnectionStatus == OTSessionConnectionStatusConnected ||
self.session.sessionConnectionStatus == OTSessionConnectionStatusConnecting ) ) {
// Get a token by calling Parse Cloud Code function
[PFCloud callFunctionInBackground:@"getBroadcastToken"
withParameters:@{ @"broadcast" : self.broadcast.objectId }
block:^(NSString *token, NSError *error) {
if (!error) {
[self.session connectWithApiKey:kOpentokApiKey token:token];
[self configureView];
}
}];
}
}
// ...
@end
// Import the opentok library from the subdirectory
var opentok = require('cloud/opentok/opentok.js').createOpenTokSDK('OPENTOK_API_KEY', 'OPENTOK_API_SECRET');
// Every Broadcast object should "own" an OpenTok Session
Parse.Cloud.beforeSave("Broadcast", function(request, response) {
var broadcast = request.object;
// If this Broadcast already has a sessionId, we are done
if (broadcast.get("sessionId")) { response.success(); return; }
// Otherwise, we create a Session now...
opentok.createSession(function(err, sessionId) {
// Handle any errors
if (err) { response.error("could not create opentok session for broadcast: " + broadcast.id); return; }
// ... and now save the sessionId in the Broadcast object
broadcast.set("sessionId", sessionId);
response.success();
});
});
// This function can be called by any user who wants to connect to a Broadcast and a Token with the
// corresponding `role` will be generated. (Publisher for the Broadcast owner, Subscriber for anyone else)
Parse.Cloud.define("getBroadcastToken", function(request, response) {
// Retrieve the Broadcast object for which the token is being requested
var broadcastId = request.params.broadcast;
if (!broadcastId) response.error("you must provide a broadcast object id");
var broadcastQuery = new Parse.Query("Broadcast");
broadcastQuery.get(broadcastId, {
// When the Broadcast object is found...
success: function(broadcast) {
// Get the appropriate role according to the user who is calling this function
var role = roleForUser(broadcast, request.user);
// Create a Token
var token = opentok.generateToken(broadcast.get("sessionId"), { "role" : role });
// Return the token as long as it exists
if (token) {
response.success(token);
// Handle errors
} else {
response.error("could not generate token for broadcast id: " + broadcastId + " for role: " + role);
}
},
// When the Broadcast object is not found, respond with error
error: function(broadcast, error) {
response.error("cannot find broadcast with id: " + broadcastId);
}
});
});
// Helper function to figure out the OpenTok role a user should get based on the Boradcast object
var roleForUser = function(broadcast, user) {
// A Broadcast owner gets a Publisher token
if (broadcast.get("owner").id === user.id) {
return opentok.ROLE.PUBLISHER;
// Anyone else gets a Subscriber token
} else {
return opentok.ROLE.SUBSCRIBER;
}
};
@implementation BroadcastViewController
// ...
- (BOOL)isBroadcastOwner {
return [[(PFUser *)self.broadcast[@"owner"] objectId] isEqual:[[PFUser currentUser] objectId]];
}
// ...
- (void)sessionDidConnect:(OTSession *)session
{
// Publish if this user owns this broadcast
if ([self isBroadcastOwner]) {
OTPublisher *publisher = [[OTPublisher alloc] initWithDelegate:self];
[self.session publish:publisher];
}
[self configureView];
}
// ...
- (void)session:(OTSession *)session didReceiveStream:(OTStream *)stream
{
if (![self isBroadcastOwner]) {
__unused OTSubscriber *subscriber = [[OTSubscriber alloc] initWithStream:stream delegate:self];
}
}
// ...
@end
# Install the `parse` CLI
$ curl -s https://www.parse.com/downloads/cloud_code/installer.sh | sudo /bin/bash
# Create and enter the project directory
$ mkdir -p ~/projects/Broadcasts && cd ~/projects/Broadcasts
# Set up a new parse project
$ parse new
Creating a new project in directory /Users/USERNAME/projects/Broadcasts/parse
Creating directory /Users/USERNAME/projects/Broadcasts/parse/config
Creating config file /Users/USERNAME/projects/Broadcasts/parse/config/global.json
Creating directory /Users/USERNAME/projects/Broadcasts/parse/cloud
Writing out sample file /Users/USERNAME/projects/Broadcasts/parse/cloud/main.js
Email: your@email.com
Password:
1: Broadcasts
Select an App: 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment