This website uses cookies for anonymised tracking and analytics. The tracking software used is called Matomo and is self-hosted. Your data never leaves this server and is not used for advertising or other nefarious purposes. By clicking accept, you agree to the privacy policy and to the use of cookies in tracking your use of the website. If, at a later time, you want to opt-out from this decision, visit this page.

Kudusch’s Trash

A blog about Life, the Universe and Everything…


Notice: start_wp is deprecated since version 1.5.0! Use new WordPress Loop instead. in /var/www/html/apps/wordpress/wp-includes/functions.php on line 3853

ColorClock screensaver

February 12, 2014

Time and color, combined into a screensaver!

This Mac OSX screensaver displays the current time and its RGB-color equivalent. In 24 hours the red-value goes from 0 to 255, the green and blue values do so in 60 minutes/seconds.
So at midnight you’ll have black and at 23:59:59 you’ll have white. And in between you’ll find every other color in the RGB-spectrum.

This is not my original idea. I saw a flash version of this concept a few years ago and rebuild it with javascript. You can find the original here.
The Mac OSX screensaver wrapper is from this project. See the readme.md for licensing.

The screensaver is available with either Helvetica Neue or a monospace font (Menlo).

Download:

If you don’t have a Mac or just don’t want to use a screensaver, you can visit the web version here (monospace) and here (Helvetica).

Tags: colorcsshtmljavascriptMac OSXrgbscreensaver

Notice: start_wp is deprecated since version 1.5.0! Use new WordPress Loop instead. in /var/www/html/apps/wordpress/wp-includes/functions.php on line 3853

Gehacktes für den ARD Mediathek Download (HTTP Live Streaming .ts files download and merge)

December 29, 2013

Ein kleines php-Skript um Videos aus der ARD Mediathek (oder anderen Diensten, die HLS anbieten) herunter zuladen.

How to use

  • go to http://mediathek.daserste.de, open with iPad User Agent
  • navigate to the desired program, get link to the master.m3u8 file from source (in the video-tag)
  • run the script with url to the master.m3u8 file as argument (e.g. php get_tshls ‘http://http://hls.daserste.de/i/…/ios.smil/master.m3u8’
  • wait for the script to download and merge all media files; every 10 second part is about 3 MB (when it’s done, it will output the runtime)
  • if necessary, convert the *.ts file with a media converter eg. handbrake to a *.mp4 file
  • enjoy
<?php
/*
Made by Kudusch (blog.kudusch.de, kudusch.de, @Kudusch)

---------

DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
 Version 2, December 2004 

Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified 
copies of this license document, and changing it is allowed as long 
as the name is changed. 

DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 
 
0. You just DO WHAT THE FUCK YOU WANT TO.

---------

# How to use

- go to http://mediathek.daserste.de, open with iPad User Agent
- navigate to the desired program, get link to the master.m3u8 file from source (in the <video>-tag)
- run the script with url to the master.m3u8 file as argument (e.g. php get_tshls 'http://http://hls.daserste.de/i/videoportal/Film/c_380000/386059/ios.smil/master.m3u8'
- wait for the script to download and merge all media files; every 10 second part is about 3 MB (when it's done, it will output the runtime)
- if necessary, convert the *.ts file with a media converter eg. handbrake to a *.mp4 file
- enjoy

*/

//runtime
$startTime = microtime(get_as_float);

//get url from input
$url = $argv[1];
//get stream with highest bandwith
$streamUrl = getHighBandwidthStream($url);
//get array of all links to *.ts files
$list = getHlsFiles($streamUrl);

//make new directory
if (!is_dir('files')) {
 mkdir('files');
}

//download all files from array, name with 3 leading zeros
//if file is longer than 166.5 minutes, adjust str_pad params
$n = 1;
foreach ($list as $key) {
 $number = str_pad($n, 3, "0", STR_PAD_LEFT);
 print_r($n." ");
 file_put_contents("files/part.".$number.".ts", fopen($key, 'r'));
 $n++;
}

//merge files and delte parts
sleep(10);
mergeFiles('files');

//echo part numbers and runtime for debugging
echo("\nRun in ".(microtime(get_as_float)-$startTime)." seconds.");

//input: string, output: string
function getHighBandwidthStream($masterUrl) {
 //get content of master.m3u8
 $ch = curl_init($masterUrl);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
 $result = curl_exec($ch);
 curl_close($ch);
 
 //return link to second last stream (https://developer.apple.com/library/ios/documentation/networkinginternet/conceptual/streamingmediaguide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html#//apple_ref/doc/uid/TP40008332-CH103-SW1)
 $result = split("#", $result);
 for ($i = 0; $i < 2; $i++) {
 array_shift($result);
 }
 $length = count($result);
 $result = split("\n", $result[$length-2]);
 return $result[1];
}

//input: string, output: array
function getHlsFiles($streamUrl) {
 //get content of *.m3u8 file
 $ch = curl_init($streamUrl);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
 $raw = curl_exec($ch);
 curl_close($ch);
 
 //remove comments and unnecessary data
 $list_raw = split("\n", $raw);
 for ($i = 0; $i < 5; $i++) {
 array_shift($list_raw);
 }
 for ($i = 0; $i < 2; $i++) {
 array_pop($list_raw);
 }
 
 //extract file links 
 $list = array();
 $i = 1;
 foreach ($list_raw as $key) {
 if($i%2 == 0) {
 array_push($list, $key);
 }
 $i++;
 }
 
 //return array
 return $list;
}

function mergeFiles($dirName) {
 //get all *.ts files in directory
 if ($handle = opendir($dirName)) {
 while (false !== ($file = readdir($handle))) {
 if (strpos($file, ".ts") !== false) {
 $fileList = $fileList." files/".$file;
 }
 }
 closedir($handle);
 }
 
 //join and remove parts
 $shellScript = "cat ".substr($fileList, 1)." >> movie.ts";
 shell_exec($shellScript);
 shell_exec("rm -r files");
}
?>
Tags: ard mediathekcatgehackteshlsHTTP Live Streamingmergephpscriptts

Notice: start_wp is deprecated since version 1.5.0! Use new WordPress Loop instead. in /var/www/html/apps/wordpress/wp-includes/functions.php on line 3853

ASCII Converter for Alfred 2

March 19, 2013

This is another little workflow for the Alfred Powerpack

image

image

With this workflow you can convert a string of characters into their ASCII code values and vice versa.
You can convert from and to hexadecimal, binary and decimal.
The results will be displayed as soon as you run the workflow and copied to your clipboard when you press enter.

You can either enter a string or just use your clipboard content.

ASCII converter

 

This extension is written in AppleScript and does not require an internet connection to work; the conversion is done inside the script and does not rely on an extern service.

Enjoy.

If you experience any problem with this extension, found a bug or have feature request, hit me on twitter.

Changelog:
Version 1.1
-fixes a rather stupid bug where the conversion for hex would not be in hexadecimal, but in hexal

Version 1.0
-rewritten as an Alfred 2 workflow
-detection of input

 


Notice: start_wp is deprecated since version 1.5.0! Use new WordPress Loop instead. in /var/www/html/apps/wordpress/wp-includes/functions.php on line 3853

Control Notification Center and Growl.app from Alfred.app

March 16, 2013

An Alfred v2 workflow to control Growl.app and Mountain Lion’s Notification Center.
You’ll need version +1.3 of Growl.

You can use the following keywords:

Show the current status of Growl and NotificationCenter : stat
Pause Growl and Notification Center : pause
Resume Growl and Notification Center : resume
Pause or resume Growl : growl
Pause or resume Notification Center : notificationcenter
Close all Growl notifications : close_growl
Close all NotificationCenter notifications : close_nc
Show Growl’s rollup : show
Hide Growl’s rollup : hide
Enable Growl’s incoming network : enable
Disable Growl’s incoming network : disable/
Restart Growl : restart

Just download this extension, install it and it’s ready to use.

If you don’t have Growl installed, you can just download the NotificationCenter only version of the workflow.

Download!
(Growl and NotificationCenter)

 

Download!
(NotificationCenter only)

This extension is written in AppleScript and uses the Shell.

If you experience any troubles with this, hit me on twitter.
Enjoy.

Changelog:
v.2.3:
-support for Mac OS X 10.10 Yosemite
-you can now download this workflow in two versions (one with growl, one without)
v.2.2:
-added support for Mac OS X 10.9 Mavericks’ new security features
v.2.1:
-added support for Mac OS X 10.9 Mavericks
v.2.0.0:
-now rewritten as an Alfred 2 workflow
-added option to close all pending NotificationCenter items

If you don’t have the Alfred Powerpack or you don’t want to use Alfred for this task, you can either extract the code from the workflow file or just ask me for the source.


Notice: start_wp is deprecated since version 1.5.0! Use new WordPress Loop instead. in /var/www/html/apps/wordpress/wp-includes/functions.php on line 3853

How to build your own Memomail

February 3, 2013

If you are fortunate enough, you might already have your twitter archive.
And if you set up Tweet Nest on your server, you might enjoy this little php snippet.

This is basically a more usable version of Memolane’s Memomail.

<?php
//execution time
$startTime = microtime('get_as_float');

// set date and time
date_default_timezone_set("Europe/Berlin");
$day = date('d');
$month = date('m');
$dayName = date('jS');
$monthName = date('F');
$currentYear = intval(date('Y'));

file_put_contents('index.html', '<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css" type="text/css">
<title>Twitter memories of '.$monthName.' '.$dayName.'</title>
</head>
<body>
<div class="main">
<h1><a class="head" href="">Twitter memories of <br>'.$monthName.' '.$dayName.'</a></h1>');

for ($i = 1; $i <= 3; $i++) {
	$offSet = $i;
	$year = $currentYear - $offSet;
	if ($i == 1) {
		$h2 = $i." year ago…";
	} else {
		$h2 = $i." years ago…";
	}
	$apiCall = "http://yourdomain.tld/path/to/tweetnest/{$year}/{$month}/{$day}";
	file_put_contents('index.html', '<div class="tweets" id="tweets_'.$i.'"><div class="title">'.$h2.'</div>'.getTweets($apiCall)."</div><hr>",FILE_APPEND);
}

file_put_contents('index.html', '<div id="footer">Made with php, css and love by <a href="http://kudusch.de/">Kudusch</a></div></div></body></html>',FILE_APPEND);

//premailer
$url = "http://yourdomain.tld/path/to/this/scriptfolder/index.html";
$pre = Premailer::url($url);
$html = $pre['html'];

// Set up parameters for mail
$to = "mail@yourdomain.tld";
$subject = "Twitter memories of {$monthName} {$dayName}";
$message = $html;
$from = "mail@yourdomain.tld";
$headers = "MIME-Version: 1.0" . "\n";
$headers .= "Content-Type: text/html; charset=UTF-8" . "\n";
$headers .= "From: $from" . "\n";

// Send email
mail($to,$subject,$message,$headers);
echo("Done.<br>Run in ".(microtime('get_as_float')-$startTime));

// convert external css to inline style using premailer
/**
 * Premailer API PHP class
 * Premailer is a library/service for making HTML more palatable for various inept email clients, in particular GMail
 * Primary function is to convert style tags into equivalent inline styles so styling can survive <head> tag removal
 * Premailer is owned by Dialect Communications group
 * @link http://premailer.dialect.ca/api
 * @author Marcus Bointon <marcus@synchromedia.co.uk>
 */
 
class Premailer {
	/**
	 * The Premailer API URL
	 */
	const ENDPOINT = 'http://premailer.dialect.ca/api/0.1/documents';
	static $CI ;
	public function __construct()
	{
		self::$CI =& get_instance();
		self::$CI->load->library('my_curl');
		
	}
	/**
	 * Central static method for submitting either an HTML string or a URL, optionally retrieving converted versions
	 * @static
	 * @throws Exception
	 * @param string $html Raw HTML source
	 * @param string $url URL of the source file
	 * @param bool $fetchresult Whether to also fetch the converted output
	 * @param string $adaptor Which document handler to use (hpricot (default) or nokigiri)
	 * @param string $base_url Base URL for converting relative links
	 * @param int $line_length Length of lines in the plain text version (default 65)
	 * @param string $link_query_string Query string appended to links
	 * @param bool $preserve_styles Whether to preserve any link rel=stylesheet and style elements
	 * @param bool $remove_ids Remove IDs from the HTML document?
	 * @param bool $remove_classes Remove classes from the HTML document?
	 * @param bool $remove_comments Remove comments from the HTML document?
	 * @return array Either a single strclass object containing the decoded JSON response, or a 3-element array containing result, html and plain parts if $fetchresult is set
	 */
	protected static function convert($html = '', $url = '', $fetchresult = true, $adaptor = 'hpricot', $base_url = '', $line_length = 65, $link_query_string = '', $preserve_styles = true, $remove_ids = false, $remove_classes = false, $remove_comments = false) {
		$params = array();
		if (!empty($html)) {
			$params['html'] = $html;
		} elseif (!empty($url)) {
			$params['url'] = $url;
		} else {
			throw new Exception('Must supply an html or url value');
		}
		if ($adaptor == 'hpricot' or $adaptor == 'nokigiri') {
			$params['adaptor'] = $adaptor;
		}
		if (!empty($base_url)) {
			$params['base_url'] = $base_url;
		}
		$params['line_length'] = (integer)$line_length;
		if (!empty($link_query_string)) {
			$params['link_query_string'] = $link_query_string;
		}
		$params['preserve_styles'] = ($preserve_styles? 'true':'false');
		$params['remove_ids'] = ($remove_ids? 'true':'false');
		$params['$remove_classes'] = ($remove_classes? 'true':'false');
		$params['$remove_comments'] = ($remove_comments? 'true':'false');
		$options = array(
			'timeout' => 15,
			'connecttimeout' => 15,
			'useragent' => 'PHP Premailer',
			'ssl' => array('verifypeer' => false, 'verifyhost' => false)
		);
	//	$h = new HttpRequest(self::ENDPOINT, HttpRequest::METH_POST, $options);
		
	
		$conf = array(
				'url'	=> self::ENDPOINT,
				'timeout' => 15,
				'useragent' => 'PHP Premailer',
				'ssl_verifyhost'	=> 0,
				'SSL_VERIFYPEER'	=> 0,
				'post'		=> 1,
				'postfields' => $params,
				'returntransfer' => true,
				'httpheader' => array("Expect:")
			);
		
		foreach($conf as $key => $value){
			$name = constant('CURLOPT_'.strtoupper($key));
			$val  = $value;
			$data_conf[$name] = $val;
		}
		$cu = curl_init();
		curl_setopt_array($cu, $data_conf);
		$exec = curl_exec($cu);	
		$_res			= json_decode($exec);
		$_res_info 	= json_decode(json_encode(curl_getinfo($cu))); 	
		curl_close($cu);
		if($_res_info->http_code != 201){
			$code = $_res_info->http_code;
			switch ($code) {
				case 400:
					throw new Exception('Content missing', 400);
					break;
				case 403:
					throw new Exception('Access forbidden', 403);
					break;
				case 500:
				default:
					throw new Exception('Error', $code);
			}
			
		}
		$return = array('result' => $_res);
		if ($fetchresult) {
			$html = curl_init();
			curl_setopt_array(
					$html, array(
						CURLOPT_URL 			=> $_res->documents->html,
						CURLOPT_TIMEOUT 		=> 15,
						CURLOPT_USERAGENT 		=> 'PHP Premailer',
						CURLOPT_SSL_VERIFYHOST	=> 0,
						CURLOPT_SSL_VERIFYPEER	=> 0,
						CURLOPT_HTTPHEADER 		=> array("Expect:"),
						CURLOPT_RETURNTRANSFER 	=> true
					)
				);
			$return['html'] = curl_exec($html);
			curl_close($html);
			
			$plain = curl_init();
			curl_setopt_array(
					$plain, array(
						CURLOPT_URL 			=> $_res->documents->txt,
						CURLOPT_TIMEOUT 		=> 15,
						CURLOPT_USERAGENT 		=> 'PHP Premailer',
						CURLOPT_SSL_VERIFYHOST	=> 0,
						CURLOPT_SSL_VERIFYPEER	=> 0,
						CURLOPT_HTTPHEADER 		=> array("Expect:"),
						CURLOPT_RETURNTRANSFER 	=> true
					)
				);
			$return['plain'] = curl_exec($plain);
			curl_close($plain);
		
			return $return;
		}
		return $result;
		
	}
 
	/**
	 * Central static method for submitting either an HTML string or a URL, optionally retrieving converted versions
	 * @static
	 * @throws Exception
	 * @param string $html Raw HTML source
	 * @param bool $fetchresult Whether to also fetch the converted output
	 * @param string $adaptor Which document handler to use (hpricot (default) or nokigiri)
	 * @param string $base_url Base URL for converting relative links
	 * @param int $line_length Length of lines in the plain text version (default 65)
	 * @param string $link_query_string Query string appended to links
	 * @param bool $preserve_styles Whether to preserve any link rel=stylesheet and style elements
	 * @param bool $remove_ids Remove IDs from the HTML document?
	 * @param bool $remove_classes Remove classes from the HTML document?
	 * @param bool $remove_comments Remove comments from the HTML document?
	 * @return array Either a single element array containing the 'result' object, or three elements containing result, html and plain if $fetchresult is set
	 */
	public static function html($html, $fetchresult = true, $adaptor = 'hpricot', $base_url = '', $line_length = 65, $link_query_string = '', $preserve_styles = true, $remove_ids = false, $remove_classes = false, $remove_comments = false) {
		return self::convert($html, '', $fetchresult, $adaptor, $base_url, $line_length, $link_query_string, $preserve_styles, $remove_ids, $remove_classes, $remove_comments);
	}
 
	/**
	 * Central static method for submitting either an HTML string or a URL, optionally retrieving converted versions
	 * @static
	 * @throws Exception
	 * @param string $url URL of the source file
	 * @param bool $fetchresult Whether to also fetch the converted output
	 * @param string $adaptor Which document handler to use (hpricot (default) or nokigiri)
	 * @param string $base_url Base URL for converting relative links
	 * @param int $line_length Length of lines in the plain text version (default 65)
	 * @param string $link_query_string Query string appended to links
	 * @param bool $preserve_styles Whether to preserve any link rel=stylesheet and style elements
	 * @param bool $remove_ids Remove IDs from the HTML document?
	 * @param bool $remove_classes Remove classes from the HTML document?
	 * @param bool $remove_comments Remove comments from the HTML document?
	 * @return array Either a single element array containing the 'result' object, or three elements containing result, html and plain if $fetchresult is set
	 */
	public static function url($url, $fetchresult = true, $adaptor = 'hpricot', $base_url = '', $line_length = 65, $link_query_string = '', $preserve_styles = true, $remove_ids = false, $remove_classes = false, $remove_comments = false) {
		return self::convert('', $url, $fetchresult, $adaptor, $base_url, $line_length, $link_query_string, $preserve_styles, $remove_ids, $remove_classes, $remove_comments);
	}
}

function getTweets($apiCall) {
	// Get html via curl
	$ch = curl_init($apiCall);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
	$html = curl_exec($ch);
	curl_close($ch);

	$dom = new DomDocument();
	$dom->loadHtml($html);
	$tweets = getElementsByClassname($dom, "tweet");
	$length = $tweets->length;

	$result = "";

	foreach ($tweets as $tweet) {
		$result .= '<div class="tweet">'.get_inner_html($tweet).'</div><br>';
	}

	if ($result == "") {
		return '<p class="empty">No tweets here!</p>';
	} else {
		return $result;
	}
}

function getElementsByClassname( DOMDocument $doc, $classname ) 
{   
    $xpath = new DOMXPath( $doc );

    // XPath 1.0
    $nodes = $xpath->query( "//*[contains( normalize-space( @class ), ' $classname ' ) or substring( normalize-space( @class ), 1, string-length( '$classname' ) + 1 ) = '$classname ' or substring( normalize-space( @class ), string-length( @class ) - string-length( '$classname' ) ) = ' $classname' or @class = '$classname']" );
    return $nodes;
}

function printNodeList( DOMNodeList $nodeList ) 
{
    foreach( $nodeList as $node ) 
    {
        echo '<', $node->tagName, '> ', $node->nodeValue, ' <', $node->tagName, '> ', "\n";
    }
}

function get_inner_html( $node ) { 
    $innerHTML= ''; 
    $children = $node->childNodes; 
    foreach ($children as $child) { 
        $innerHTML .= $child->ownerDocument->saveXML( $child ); 
    } 

    return $innerHTML; 
} 
?>

It fetches the tweets from 1, 2 and 3 years ago from your Tweet Nest via curl, removes everything but the header and the tweets and sends you an HTML mail.

You can set this up with a cronjob for automatic mails.

This snippet is roughly commented and not documented.
I just wanted to share this for you to build upon.

Kudos to:
http://premailer.dialect.ca/api
https://gist.github.com/1591053
http://pongsocket.com/tweetnest/

previous page

Impressum / RSS / kudusch.de