/[drupal]/contributions/modules/twistage/twistage_syndicate.module
ViewVC logotype

Contents of /contributions/modules/twistage/twistage_syndicate.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Tue Oct 7 15:16:56 2008 UTC (13 months, 2 weeks ago) by xmattus
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--1
Changes since 1.1: +2 -2 lines
File MIME type: text/x-php
Adding multi-video posting functionality, and a few bug fixes-
1 <?php
2
3 function twistage_syndicate_menu($may_cache) {
4 $items = array();
5
6 $items[] = array(
7 'path' => 'twistage/syn/test',
8 'type' => MENU_CALLBACK_ITEM,
9 'callback' => 'twistage_syndicate_youtube',
10 'access' => user_access('access content'),
11 );
12
13 $items[] = array(
14 'path' => 'admin/settings/twistage/syndication',
15 'type' => MENU_CALLBACK,
16 'title' => t('Syndication status'),
17 'callback' => 'twistage_syndicate_status',
18 'callback arguments' => array(arg(4)),
19 'access' => user_access('administer twistage'),
20 );
21
22 $items[] = array(
23 'path' => 'admin/settings/twistage/synconfig',
24 'type' => MENU_CALLBACK,
25 'title' => t('Syndication settings'),
26 'callback' => 'drupal_get_form',
27 'callback arguments' => 'twistage_syndicate_admin_form',
28 'access' => user_access('administer twistage'),
29 );
30
31 $items[] = array(
32 'path' => 'admin/settings/twistage/syndication/force',
33 'type' => MENU_CALLBACK,
34 'callback' => 'twistage_syndicate_force_push',
35 'callback arguments' => array(arg(5), arg(6)),
36 'access' => user_access('administer twistage'),
37 );
38
39 $items[] = array(
40 'path' => 'twistage/itunes',
41 'type' => MENU_CALLBACK_ITEM,
42 'callback' => 'twistage_syndicate_itunes_stream',
43 'access' => user_access('access content'),
44 );
45
46 return $items;
47 }
48
49 /**
50 * Implementation of hook_twistage_api
51 */
52 function twistage_syndicate_twistage_api($op, $video) {
53 /*if (!$video->syndicated) {
54 twistage_syndicate_push_all($video->pid, $video->vid);
55 }*/
56
57 switch($op) {
58 case 'order add':
59 if (!$video->syndicated) {
60 twistage_syndicate_push_all($video->pid, $video->vid);
61 }
62 break;
63
64 }
65 }
66
67 function twistage_syndicate_admin_form() {
68 $form = array();
69
70 $form['youtube'] = array(
71 '#type' => 'fieldset',
72 '#title' => t('YouTube settings'),
73 );
74
75 $form['youtube']['yt_username'] = array(
76 '#type' => 'textfield',
77 '#title' => t('YouTube username'),
78 '#description' => t('The username of the YouTube account which will own the syndicated videos'),
79 '#default_value' => variable_get('twistage_syndicate_youtube_username', ''),
80 );
81
82 $form['youtube']['yt_password'] = array(
83 '#type' => 'textfield',
84 '#title' => t('YouTube password'),
85 '#description' => t('The password to the YouTube account'),
86 '#default_value' => variable_get('twistage_syndicate_youtube_password', ''),
87 );
88
89 $form['youtube']['yt_client_id'] = array(
90 '#type' => 'textfield',
91 '#title' => t('YouTube client ID'),
92 '#description' => t('An identifier that you must obtain from the <a href="http://code.google.com/apis/youtube/dashboard">YouTube Developer Dashboard</a>'),
93 '#default_value' => variable_get('twistage_syndicate_youtube_client_id', ''),
94 );
95
96 $form['youtube']['yt_developer_key'] = array(
97 '#type' => 'textfield',
98 '#title' => t('YouTube developer key'),
99 '#description' => t('An identifier that you must obtain from the <a href="http://code.google.com/apis/youtube/dashboard">YouTube Developer Dashboard</a>'),
100 '#default_value' => variable_get('twistage_syndicate_youtube_developer_key', ''),
101 );
102
103 $form['blip'] = array(
104 '#type' => 'fieldset',
105 '#title' => t('Blip.tv settings'),
106 );
107
108 $form['blip']['blip_username'] = array(
109 '#type' => 'textfield',
110 '#title' => t('Blip.tv username'),
111 '#description' => t('The username of the Blip.tv account which will own the syndicated videos'),
112 '#default_value' => variable_get('twistage_syndicate_blip_username', ''),
113 );
114
115 $form['blip']['blip_password'] = array(
116 '#type' => 'textfield',
117 '#title' => t('Blip.tv password'),
118 '#description' => t('The password of the Blip.tv account'),
119 '#default_value' => variable_get('twistage_syndicate_blip_password', ''),
120 );
121
122 $form['itunes'] = array(
123 '#type' => 'fieldset',
124 '#title' => t('iTunes Podcast settings'),
125 );
126
127 $form['itunes']['info'] = array(
128 '#value' => t('In order to generate an iTunes-compatible podcast, the videos in your Twistage
129 profile must have an MP4 video asset associated with them. You can manually generate
130 one for a given video by going to <i>http://service.twistage.com/videos/[video_id]/asset_summary</i>
131 and selecting "MP4 for Apple portable devices" (whichever size you prefer). You can also configure Twistage
132 to auto-generate this asset upon upload using the "Publish profiles" settings.'),
133 );
134
135 $form['itunes']['itunes_title'] = array(
136 '#type' => 'textfield',
137 '#title' => t('Podcast title'),
138 '#description' => t('The title of the podcast'),
139 '#default_value' => variable_get('twistage_syndicate_itunes_title', ''),
140 );
141
142 $form['itunes']['itunes_summary'] = array(
143 '#type' => 'textfield',
144 '#title' => t('Podcast summary'),
145 '#description' => t('Will be shown in iTunes in the "Description" column'),
146 '#default_value' => variable_get('twistage_syndicate_itunes_summary', ''),
147 );
148
149 $form['itunes']['itunes_author'] = array(
150 '#type' => 'textfield',
151 '#title' => t('Podcast author'),
152 '#description' => t('Will be shown in the Podcast preview page in iTunes'),
153 '#default_value' => variable_get('twistage_syndicate_itunes_author',''),
154 );
155
156 $form['itunes']['itunes_email'] = array(
157 '#type' => 'textfield',
158 '#title' => t('Podcast contact email'),
159 "#description" => t('Email which Apple can use to contact you. Not shown publicly.'),
160 '#default_value' => variable_get('twistage_syndicate_itunes_email',''),
161 );
162
163 $form['itunes']['itunes_image'] = array(
164 '#type' => 'textfield',
165 '#title' => t('Podcast image URL'),
166 "#description" => t('URL to an image which will be shown on the podcast preview page.'),
167 '#default_value' => variable_get('twistage_syndicate_itunes_image',''),
168 );
169
170 $form['itunes']['itunes_category'] = array(
171 '#type' => 'textfield',
172 '#title' => t('Podcast category'),
173 "#description" => t('A comma-separated list of categories.'),
174 '#default_value' => variable_get('twistage_syndicate_itunes_category',''),
175 );
176
177 $form['itunes']['itunes_link'] = array(
178 '#type' => 'textfield',
179 '#title' => t('Podcast link'),
180 "#description" => t('A link to be associated with the podcast.'),
181 '#default_value' => variable_get('twistage_syndicate_itunes_link',''),
182 );
183
184
185 /*
186 $form['vimeo'] = array(
187 '#type' => 'fieldset',
188 '#title' => t('Vimeo settings'),
189 );
190
191 $form['vimeo']['vimeo_developer_key'] = array(
192 '#type' => 'textfield',
193 '#title' => t('Vimeo developer key'),
194 '#description' => t('The developer key that Vimeo has provided to you at their <a href="http://www.vimeo.com/api">developer page</a>'),
195 '#default_value' => variable_get('twistage_syndicate_vimeo_developer_key', ''),
196 );
197
198 $form['vimeo']['vimeo_secret_key'] = array(
199 '#type' => 'textfield',
200 '#title' => t('Vimeo secret key'),
201 '#description' => t('The secret key that Vimeo has provided to you at their <a href="http://www.vimeo.com/api">developer page</a>'),
202 '#default_value' => variable_get('twistage_syndicate_vimeo_secret_key', ''),
203 );
204 */
205
206 return system_settings_form($form);
207 }
208
209 function twistage_syndicate_admin_form_submit($form_id, $form_values) {
210 variable_set('twistage_syndicate_youtube_username', $form_values['yt_username']);
211 variable_set('twistage_syndicate_youtube_password', $form_values['yt_password']);
212 variable_set('twistage_syndicate_youtube_client_id', $form_values['yt_client_id']);
213 variable_set('twistage_syndicate_youtube_developer_key', $form_values['yt_developer_key']);
214
215 variable_set('twistage_syndicate_blip_username', $form_values['blip_username']);
216 variable_set('twistage_syndicate_blip_password', $form_values['blip_password']);
217
218 variable_set('twistage_syndicate_vimeo_developer_key', $form_values['vimeo_developer_key']);
219 variable_set('twistage_syndicate_vimeo_secret_key', $form_values['vimeo_secret_key']);
220
221 variable_set('twistage_syndicate_itunes_summary', $form_values['itunes_summary']);
222 variable_set('twistage_syndicate_itunes_author', $form_values['itunes_author']);
223 variable_set('twistage_syndicate_itunes_email', $form_values['itunes_email']);
224 variable_set('twistage_syndicate_itunes_image', $form_values['itunes_image']);
225 variable_set('twistage_syndicate_itunes_category', $form_values['itunes_category']);
226 variable_set('twistage_syndicate_itunes_link', $form_values['itunes_link']);
227 variable_set('twistage_syndicate_itunes_title', $form_values['itunes_title']);
228
229 drupal_set_message('Syndication settings saved.');
230
231 return 'admin/settings/twistage';
232 }
233
234 function twistage_syndicate_force_push($pid, $vid) {
235 twistage_syndicate_push_all($pid, $vid);
236 $content = '<p>Syndication was completed. Please check the message queue for status.</p><p><a href="/admin/settings/twistage/syndication/'.$pid.'">Click here to return to syndication status listing</a>.</p>';
237 return $content;
238 //drupal_goto('admin/settings/twistage/syndication/' . $pid);
239 }
240
241 function twistage_syndicate_push_all($pid, $vid) {
242 db_query("UPDATE {twistage_videos} SET syndicated=1 WHERE vid='%s' AND pid=%d", $vid, $pid);
243
244 twistage_syndicate_blip_push($vid, $pid);
245 twistage_syndicate_youtube_push($vid, $pid);
246 //twistage_syndicate_vimeo_push($vid, $pid);
247
248 drupal_set_message('Syndication complete for video ID ' . $vid . '.');
249 return;
250 //drupal_goto('admin/settings/twistage');
251 }
252
253 function twistage_syndicate_status($pid) {
254 $profile = twistage_get_profile($pid);
255
256 $header = array(
257 'Video title',
258 'Video ID',
259 'Syndicated',
260 'Operations',
261 );
262
263 $syn = array(0 => 'No', 1 => 'Yes');
264
265 $result = db_query("SELECT * FROM {twistage_videos} WHERE pid=%d AND site_key='%s'", $profile->pid, $profile->site_key);
266
267 $rows = array();
268 while ($video = db_fetch_object($result)) {
269 $rows[] = array(
270 $video->title,
271 $video->vid,
272 $syn[$video->syndicated],
273 '<a href="/admin/settings/twistage/syndication/force/' . $profile->pid . '/' . $video->vid . '">force syndicate now</a>',
274 );
275 }
276
277 return theme('table', $header, $rows);
278 }
279
280 // This functionality was discontinued when it became apparent the Vimeo API was too inscrutable (at least for me)
281 /*
282 function twistage_syndicate_vimeo_push($vid, $pid) {
283 $api_key = variable_get('twistage_syndicate_vimeo_developer_key','');
284 $secret_key = variable_get('twistage_syndicate_vimeo_secret_key','');
285 $video = twistage_get_video($vid, $pid);
286 if (!$api_key || !$secret_key) {
287 // No keys entered, exit before doing anything
288 return;
289 }
290
291 // First get Vimeo login key
292 $postfields = array(
293 'method' => 'vimeo.auth.getFrob',
294 'api_key' => $api_key,
295 'api_sig' => md5($secret_key . 'api_key' . $api_key . 'methodvimeo.auth.getFrob'),
296 );
297
298 $c = curl_init('http://www.vimeo.com/api/rest/');
299 curl_setopt($c, CURLOPT_POST, TRUE);
300 curl_setopt($c, CURLOPT_POSTFIELDS, $postfields);
301 curl_setopt($c, CURLOPT_HEADER, FALSE);
302 curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
303 $data = curl_exec($c);
304 $xml = (array)simplexml_load_string($data);
305
306 if (!$xml['frob']) {
307 drupal_set_message('Vimeo syndication failed for video "' . $video->title . '"');
308 return;
309 } else {
310 $frob = $xml['frob'];
311 }
312
313 $sig = md5($secret_key . 'api_key' . $api_key . 'frob' . $frob . 'permswrite');
314
315 $c = curl_init('http://www.vimeo.com/services/auth/?api_key=' . $api_key . '&perms=write&frob=' . $frob . '&api_sig=' . $sig);
316 curl_exec($c);
317
318 $c = curl_init('http://www.vimeo.com/api/rest/');
319
320 $postfields = array(
321 'method' => 'vimeo.auth.getToken',
322 'frob' => $frob,
323 'api_key' => $api_key,
324 'api_sig' => md5($secret_key . 'api_key' . $api_key . 'frob' . $frob . 'methodvimeo.auth.getToken'),
325 );
326
327 curl_setopt($c, CURLOPT_POST, TRUE);
328 curl_setopt($c, CURLOPT_HEADER, FALSE);
329 curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
330 curl_setopt($c, CURLOPT_POSTFIELDS, $postfields);
331
332 $data = curl_exec($c);
333 //print $data;
334 $xml = simplexml_load_string($data);
335 print_r($xml);
336 die();
337
338
339
340 $meta = twistage_fetch_metadata($video->vid, $pid);
341 $binary = file_get_contents($meta['main-asset-url']);
342 $temp = file_directory_temp() . "/" . time() . ".flv";
343 $fp = fopen($temp, "w+");
344 fwrite($fp, $binary);
345 fclose($fp);
346
347
348 }
349 */
350
351 function twistage_syndicate_blip_push($vid, $pid) {
352 $username = variable_get('twistage_syndicate_blip_username','');
353 $password = variable_get('twistage_syndicate_blip_password','');
354
355 if (!$username || !$password) {
356 // No user/pass, exit
357 return;
358 }
359
360 $video = twistage_get_video($vid, $pid);
361 $meta = twistage_fetch_metadata($video->vid, $pid);
362
363 // Blip does not require a two-step submissions or a login token, fortunately
364 // However, it needs the upload as a multipart/form-data package, and curl will only take filess from the filesystem,
365 // So we have a file to the temp. area
366 $binary = file_get_contents($meta['main-asset-url']);
367 $temp = file_directory_temp() . "/" . time() . ".flv";
368 $fp = fopen($temp, "w+");
369 fwrite($fp, $binary);
370 fclose($fp);
371
372 $postfields = array(
373 'section' => 'file',
374 'cmd' => 'post',
375 'post' => 1,
376 'userlogin' => $username,
377 'password' => $password,
378 'title' => $video->title,
379 'file' => "@".$temp,
380 );
381
382 $c = curl_init("http://uploads.blip.tv?skin=api");
383 curl_setopt($c, CURLOPT_POST, TRUE);
384 curl_setopt($c, CURLOPT_HEADER, 0);
385 curl_setopt($c, CURLOPT_POSTFIELDS, $postfields);
386 curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
387 $data = curl_exec($c);
388 $xml = simplexml_load_string($data);
389 unlink($temp);
390 curl_close($c);
391
392 if ($xml->status == "OK") {
393 drupal_set_message('The video "' . $video->title . '" was successfully added to Blip.tv.');
394 } else {
395 drupal_set_message('Blip.tv syndication failed for the video "' . $video->title . '"');
396 }
397 }
398
399 function twistage_syndicate_youtube_push($vid, $pid) {
400 $username = variable_get('twistage_syndicate_youtube_username','');
401 $password = variable_get('twistage_syndicate_youtube_password','');
402 $client_id = variable_get('twistage_syndicate_youtube_client_id','');
403 $developer_key = variable_get('twistage_syndicate_youtube_developer_key','');
404
405 if (!$username || !$password || !$client_id || !$developer_key) {
406 return;
407 }
408
409 $video = twistage_get_video($vid, $pid);
410 $meta = twistage_fetch_metadata($video->vid, $pid);
411
412 //print "Got video: \n"; print_r($video);
413 //print "Got metadata: \n"; print_r($meta);
414
415 $c = curl_init("https://www.google.com/youtube/accounts/ClientLogin");
416 curl_setopt($c, CURLOPT_POST, TRUE);
417 curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
418 curl_setopt($c, CURLOPT_HEADER, 0);
419 curl_setopt($c, CURLOPT_POSTFIELDS, "Email=" . urlencode($username) . "&Passwd=" . urlencode($password) . "&service=youtube&source=test");
420 curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
421 $data = curl_exec($c);
422 curl_close($c);
423
424 $parts = explode("\n", $data);
425 $token = substr($parts[0], 5);
426
427 //print "Got token: $token\n\n";
428
429 $binary = file_get_contents($meta['main-asset-url']);
430
431 //print "Got " . strlen($binary) . " bytes of binary video data.\n\n";
432
433 //$cliptitle = str_replace(" ", "_", $video->title);
434 $tags = array();
435 foreach($meta['tags']->tag as $item) {
436 $tags[] = str_replace(" ", "_", $item->name);
437 }
438 $keywords = implode(',', $tags);
439
440 $content = <<<CONT
441 --f727dba9
442 Content-Type: application/atom+xml; charset=UTF-8
443
444 <?xml version="1.0"?>
445 <entry xmlns="http://www.w3.org/2005/Atom"
446 xmlns:media="http://search.yahoo.com/mrss/"
447 xmlns:yt="http://gdata.youtube.com/schemas/2007">
448 <media:group>
449 <media:title type="plain">{$video->title}</media:title>
450 <media:description type="plain">
451 {$video->description}
452 </media:description>
453 <media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">People
454 </media:category>
455 <media:keywords>$keywords</media:keywords>
456 </media:group>
457 </entry>
458 --f727dba9
459 Content-Type: video/flv
460 Content-Transfer-Encoding: binary
461
462 $binary
463 --f727dba9--
464 CONT;
465
466 $len = strlen($content);
467 $post = <<<POST
468 POST /feeds/api/users/$username/uploads HTTP/1.1
469 Host: uploads.gdata.youtube.com
470 Authorization: GoogleLogin auth=$token
471 X-GData-CLient: $client_id
472 X-GData-Key: key=$developer_key
473 Slug: {$video->title}
474 Content-Type: multipart/related; boundary="f727dba9"
475 Content-Length: $len
476 Connection: close
477
478 $content
479 POST;
480
481 //print "Created post, length " . strlen($post) . "\n\n";
482
483 $fp = fsockopen("uploads.gdata.youtube.com", 80);
484 fwrite($fp, $post . "\r\n");
485
486 //print "Wrote post.\n\n";
487
488 $response = "";
489 while (!feof($fp)) {
490 $response .= fread($fp, 1024);
491 }
492
493 fclose($fp);
494
495 //print "Closed. Got response: \n"; print $response."\n\n";
496
497 if (substr($response, 0, 20) == 'HTTP/1.1 201 Created') {
498 drupal_set_message('The video "' . $video->title . '" was successfully added to YouTube.');
499 //print "Set Drupal success message.\n";
500 } else {
501 drupal_set_message('YouTube syndication failed for the video "' . $video->title . '"');
502 drupal_set_message('YouTube error: ' . $response);
503 //print "Set Drupal error message.\n";
504 }
505 //print $response."\n";
506 }
507
508 function twistage_syndicate_itunes_stream($pid) {
509 if (substr($pid, -4) == ".xml") {
510 $pid = intval(substr($pid, 0, -4));
511 }
512
513 if (!is_numeric($pid)) {
514 return;
515 }
516
517
518 $profile = twistage_get_profile($pid);
519 $result = db_query("SELECT * FROM {twistage_videos} WHERE pid=%d AND site_key='%s' AND availability='available' AND play_order>0 ORDER BY created DESC", $pid, $profile->site_key);
520
521 $channelargs = array();
522 $channelargs[] = array('key' => 'copyright', 'value' => '©' . date('Y') . ' ' . variable_get('twistage_syndicate_itunes_author',''));
523 $channelargs[] = array('key' => 'itunes:subtitle', 'value' => variable_get('twistage_syndicate_itunes_summary',''));
524 $channelargs[] = array('key' => 'itunes:author', 'value' => variable_get('twistage_syndicate_itunes_author',''));
525 $channelargs[] = array('key' => 'itunes:summary', 'value' => variable_get('twistage_syndicate_itunes_summary',''));
526 $channelargs[] = array('key' => 'itunes:owner', 'value' => array('itunes:name' => variable_get('twistage_syndicate_itunes_author',''), 'itunes:email' => variable_get('twistage_syndicate_itunes_email','')));
527 $channelargs[] = array('key' => 'itunes:image', 'attributes' => array('href' => variable_get('twistage_syndicate_itunes_image','')));
528 $channelargs[] = array('key' => 'itunes:category', 'attributes' => array('text' => variable_get('twistage_syndicate_itunes_category','')));
529
530 $items = array();
531
532 while ($video = db_fetch_object($result)) {
533 $meta = twistage_fetch_metadata($video->vid, $pid);
534 foreach ($meta['assets']->asset as $key => $val) {
535 if ($val->acodec == 'mp4a' && $val->vcodec == 'mp4v') {
536 $asset = (array)$val;
537 }
538 }
539 if (!$asset) {
540 continue; // omit this video from the feed since there's no iTunes-compatible asset
541 }
542 $durstr = floor($asset['duration'] / 60) . ":" . sprintf("%02d", round($asset['duration']) % 60);
543 $args = array();
544 $args[] = array('key' => 'itunes:author', 'value' => variable_get('twistage_syndicate_itunes_author',''));
545 $args[] = array('key' => 'itunes:subtitle', 'value' => $video->description);
546 $args[] = array('key' => 'itunes:summary', 'value' => $video->description);
547 $args[] = array('key' => 'enclosure', 'attributes' => array('url' => $asset['download-url'], 'length' => $asset['size'], 'type' => 'video/mp4'));
548 $args[] = array('key' => 'pubDate', 'value' => date('r', $video->created));
549 $args[] = array('key' => 'itunes:duration', 'value' => $durstr);
550
551 $items[] = format_rss_item($video->title, variable_get('twistage_syndicate_itunes_link',''), $video->description, $args);
552 }
553
554 $namespace = 'xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"';
555 $item_str = implode("\n", $items);
556
557 $output = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
558 $output .= '<rss ' . $namespace . '>' . "\n";
559 $output .= format_rss_channel(variable_get('twistage_syndicate_itunes_title',''),
560 variable_get('twistage_syndicate_itunes_link',''),
561 variable_get('twistage_syndicate_itunes_summary',''),
562 $item_str,
563 "en-US",
564 $channelargs);
565 $output .= "</rss>\n";
566
567 print $output;
568
569 }
570
571
572 ?>

  ViewVC Help
Powered by ViewVC 1.1.2