Category Archives: Perl

Monero Mining on Ubuntu 16.04

Account:

Der einfachste Weg einen Account zu erstellen ist auf mymonero.com. Man muss sich um keine Blockchain kümmern und es ist komplett Anonym. Auf der Seite bekommt man auch seine WalletID die wir bei dem Miner mit angeben müssen. Diese müsst Ihr bei $WALLETID ersetzen. Als Mining Pool nehmen wir monerohash.com

Installation:

apt update
apt install libcurl4-openssl-dev libncurses5-dev pkg-config automake yasm
sysctl -w vm.nr_hugepages=48 # three times more then your cpu cores
cd /opt/
git clone https://github.com/wolf9466/cpuminer-multi
cd cpuminer-multi
./autogen.sh
CFLAGS="-march=native" ./configure
make

Start:

/opt/cpuminer-multi/minerd -a cryptonight -o stratum+tcp://monerohash.com:3333/
-u $WALLETID -p $RANDOM

Reporting:

Falls man mehrere Instanzen am laufen hat, will man diese auch ein bisschen überwachen bzw. wissen was läuft. Dafür habe ich einen kleinen Bot geschrieben der mit der Monerohash IP sich die aktuellen Daten zieht und diese mir in einem Slack Channel sendet. Das ganze gibt es auf github.com.

Mojolicious mit Facebook OAuth2

Ich wollte mich einmal ein bisschen mit dem Graphen von Facebook und Authentifizierung mittels OAuth2 per Facebook schlau machen und bin dabei über den Blog Eintrag bei tudorconstantin.com gestoßen. Genaueres steht auf der Seite, jedoch ist der Code nicht sofort einsetzbar und habe ich ein mal korrigiert:

#!/usr/bin/env perl
use Mojolicious::Lite;
use Net::Facebook::Oauth2;

my $config = {
  facebook => {
      app_id => '',
      secret => '',
      redirect_url => 'http://mojo.dev:3000/redirect_from_fb',
    },
};

plugin 'o_auth2', {
  facebook => {
    key    => $config->{facebook}->{app_id},
    secret => $config->{facebook}->{secret},
}};

get '/' => sub {
  my $self = shift;

  $self->redirect_to('authenticate') unless $self->session->{user}->{fb_username};
  return $self->render('index_authenticated');
  
} => 'index';

get authenticate => sub {
  my $self = shift;

  my $url = $self->get_authorize_url(
    'facebook',
    scope => 'offline_access publish_stream user_likes email',
    redirect_uri => $config->{facebook}->{redirect_url},
  );

  $self->redirect_to( $url->to_abs->to_string );
} => 'authenticate';

get redirect_from_fb => sub {
  my $self = shift;
  my $token = $self->param('code');

  my $fb = Net::Facebook::Oauth2->new(
    application_id     => $config->{facebook}->{app_id},
    application_secret => $config->{facebook}->{secret},
    access_token       => $token,
    callback           => $config->{facebook}->{redirect_url}
  );

	my $access_token = $fb->get_access_token(code => $token);

	$fb = Net::Facebook::Oauth2->new(
		access_token => $access_token
  );

	my $info = $fb->get(
		'https://graph.facebook.com/me'
  );
							    
  print $info->as_json;

  $self->session->{user} = {
	    fb_username   => $info->as_hash->{name},
  };

  $self->redirect_to('index');
} => 'redirect_from_fb';

app->start;
__DATA__

@@ index_unauthenticated.html.ep
% layout 'default';

<%= link_to 'Click here to authenticate with FB' => 'authenticate'; %>

@@ index_authenticated.html.ep
% layout 'default';

Hello <%= session->{user}->{fb_username} %>

<%= link_to 'Click here to authenticate with FB' => 'authenticate'; %>

@@ layouts/default.html.ep
<%= content %>

oder auf gist.github.com.

Soundcloud Favorite Downloader

Früher sammelte man noch MP3 Dateien wie wild, aber das ist längst Vergangenheit. Heutzutage kann man (oder ich) gemütlich neue und alte Musik auf Soundcloud oder ähnlichen hören. Ich höre eigentlich fast ausschließlich Musik auf Soundcloud. Es gibt einfach sehr gute Musik, gerade Remixe von Liedern auf der Platform.

Leider kann man die Lieder nicht in der Soundcloud App cachen bzw. Offline hören. Deswegen ist es für das Handy eigentlich gänzlich ungeeignet, wenn man nicht seinen Traffic dafür verbrauchen will. Zum Glück bieten manche Künstler ihre Lieder zum kostenlosen Download an und das kann man sich ja zunutze machen. Dafür habe ich ein kleines Script zusammen gebastelt, das die favorisierten Lieder herunterlädt.

#!/usr/bin/perl
# script: download favorite songs from your soundcloud stream
# author: Steffen Wirth <s.wirth@itbert.de>

use WebService::Soundcloud;
use XML::Simple;
no warnings 'utf8';

# create a new app -> soundcloud.com/you/apps/new
my $client_id = "YOUR_CLIEND_ID";
my $client_secret = "YOUR_CLIENT_SECRET";
# soundcloud username and password
my $username = "YOUR_USERNAME";
my $password = "YOUR_PASSWORD";
# download path
my $file_path = "/tmp/";
    
my $scloud = WebService::Soundcloud->new($client_id, $client_secret,
	{ username => $username, password => $password, response_format => 'xml' }
);
    
# get access token
my $access_token = $scloud->get_access_token();
my $oauth_token = $access_token->{access_token};

# get favorites tracks
my $followings = $scloud->get('/users/' . $username . '/favorites');

$xml = XML::Simple->new;
$xml = XMLin($followings->content);

foreach my $item (@{$xml->{track}}) {
	my $id = $item->{id}->{content};
	my $title = $item->{title};
	my $downloadable = $item->{downloadable}->{content};
	my $downloadurl = $item->{'download-url'};

	# only download songs that are downloadable
	if ($downloadable eq "true") {

		# download track
		$title =~ s/\ /_/g;
		my $dest_file = $file_path . $id . "_" . $title . ".mp3";

		unless (-e $dest_file) {
			print "DOWNLOAD: $title ($id)" . "\n"; 
			#my $path = $scloud->download($id, $file_path);

			# verrrrrrry ugly way, but $scloud->download(); is not working.
			# have fun with big files :)
			my $track = $scloud->get($downloadurl);
			my $sound = $track->content;
			open (TRACK, ">>$dest_file");
				print TRACK $sound;
			close(TRACK);

		} else {
			print "IGNORING TRACK $title ($id)" . "\n";
		}
	}
	
}

oder auf gist.github.com

Update: ABER ABER, was machen wir mit den Liedern die wir nicht offiziell herunterladen dürfen? Dafuer gibt es Dienste wie zum Beispiel anything2mp3.com. Damit kann man auch “diese” Lieder herunterladen. Wir sind Faul, also los:

#!/usr/bin/perl
# script: download favorite songs from your soundcloud stream
# author: Steffen Wirth 

use WebService::Soundcloud;
use XML::Simple;
use HTTP::Cookies;
use LWP::Simple;
use Encode qw(encode_utf8);
no warnings 'utf8';

### settings ###

# create a new app -> soundcloud.com/you/apps/new
my $client_id = "YOUR_CLIEND_ID";
my $client_secret = "YOUR_CLIENT_SECRET";
# soundcloud username and password
my $username = "YOUR_USERNAME";
my $password = "YOUR_PASSWORD";
# download path
my $file_path = "/tmp/";
# download service
my $url = "http://anything2mp3.com/de";

### script ###

my $cookie_jar = HTTP::Cookies->new( 
    file => 'lwp_cookies.txt',
    autosave => 1,
    ignore_discard => 1,
);

my $ua = LWP::UserAgent->new;
	$ua->agent("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0");
	$ua->timeout(30);
	$ua->cookie_jar($cookie_jar);

my $scloud = WebService::Soundcloud->new($client_id, $client_secret,
	{ username => $username, password => $password, response_format => 'xml' }
);

# get access token
my $access_token = $scloud->get_access_token();
my $oauth_token = $access_token->{access_token};

# get favorites tracks
my $followings = $scloud->get('/users/' . $username . '/favorites');

$xml = XML::Simple->new;
$xml = XMLin($followings->content);

foreach my $item (@{$xml->{track}}) {
	my $id = $item->{id}->{content};
	my $title = $item->{title};
	my $downloadable = $item->{downloadable}->{content};
	my $downloadurl = $item->{'download-url'};
	my $permalink = $item->{'permalink-url'};

	# title and file 
	$title =~ s/\ /_/g;
	my $dest_file = $file_path . $id . "_" . $title . ".mp3";
	$dest_file = encode_utf8($dest_file);

	# only download songs that are downloadable
	if ($downloadable eq "true") {

		unless (-e $dest_file) {
			print "DOWNLOAD: $title" . "\n"; 
			#my $path = $scloud->download($id, $file_path);

			# verrrrrrry ugly way, but $scloud->download(); is not working.
			# have fun with big files :)
			my $track = $scloud->get($downloadurl);
			my $sound = $track->content;
			open (TRACK, ">>$dest_file");
				print TRACK $sound;
			close(TRACK);

		} else {
			print "IGNORING TRACK $title" . "\n";
		}
	} else {
		# lets download tracks that we are not supposed to

		unless (-e $dest_file) {
			print "D0WNL04D $title" . "\n";
			my $request = $ua->post($url,
				{
					url => $permalink,
					op => 'Convert',
					form_build_id => 'form-iKcdS_GJM5mRuRicuFJKS7wGB8oR7zbY6YbVeV4cjtM', # not sure how long this is valid
					form_id => 'videoconverter_form',
			});

			my $html = $ua->get($url . '/kostenlose-online-soundcloud-youtube-mp3-converter');
			$html = $html->content;

			while ($html =~ m@(((http://anything2mp3.com/de/system/temporary/mp3/))\S+[^.,!? ])@g) {
				$dl = $1;
				$dl =~ s/\>\Click//g;
			}

			($file) = $dl =~ m!([^/]+)$!;
			$file =~ s/\?download=1//g;

			my $track = $ua->get($dl);
			my $sound = $track->content;
			open (TRACK, ">>$dest_file");
				print TRACK $sound;
			close(TRACK);
		} else {
			print "IGNORING TRACK $title" . "\n";
		}

	}
	
}

auch auf gist.github.com

RSS Feeder für pushover.net (Teil 2)

Der pushover.net Dienst begeistert mich immer noch und ich habe das RSS Script um ein Channel Management erweitert. Somit lassen sich jetzt die Channel in der Datenbank speichern und man muss nicht mehr für jeden Feed einen Cronjob starten.

Das Script kann man wieder über github beziehen und dafür braucht man rss2pushover.db und rss2pushover.pl. Um einen neuen Channel hinzuzufügen muss dieser in der Datenbank gespeichert sein. Dieses kann man folgendermaßen machen:

sqlite> INSERT INTO channel (status, url, token, user) VALUES (1,$FEED_URL,$PUSH_TOKEN,$PUSH_USER);

Über den Status kann man einstellen ob der Channel aktiv (1) oder deaktiviert (0) is. Die Url ist die des RSS Feeds und Token sowie User sind von pushover für die Applikation. Anschließend kann man das Script einfach wie gewohnt starten und erhält die Push Nachrichten.

Beispiel Screenshot:

Pushover

RSS Feeder für pushover.net (Teil 1)

UPDATE: Bessere Version gibt es jetzt mit Channel Managment.

Als ich auf Android umgestiegen bin musste ich auf meine selbst geschriebenen Apps für Blackberry verzichten. Für vieles gibt es eine Android App, aber z.B. für Exbir gibt es auch nicht mal diese. Eigentlich wollte ich mir wieder meinen eigenen Pushdienst für Android aufbauen, aber momentan fehlt dafür einfach die Zeit.

Dann bin ich auf pushover.net gestoßen. Ein Dienst der einen Push Gateway anbietet und eine Android/iOS app die diese empfängt. Die App kostet 3.66 EUR und diese sind einmalig und es entstehen keine monatlichen Kosten. Ich finde das ist eine ziemlich geniale Idee, weil wer will sich schon monatlich binden. Für die Anbieter ist das auch angenehm und ich denke das diese eine Mischrechnung haben, denn viele werden die App vielleicht nicht lange benutzen.

Wenn man sich registriert hat, muss man eine Applikation erstellen und erhält einen API Key für diese. Im Monat hat man 7,500 Nachrichten inklusive und für ein paar private kleine sachen sollte das Problemlos ausreichen – pro Applikation. Man kann sich natürlich mehrere erstellen ;)

Wie bekomme ich also meine Nachrichten auf die App? Natürlich über die API und diese ist sehr einfach gehalten. Ein einfacher POST Request mit User Key und Privaten Token. Auf der Homepage findet man Beispiele von curl bis Ruby. Das Einbinden von diesem hat keine 10 Minuten gedauert und ich kann mir schon verschiedene Einsatzmöglichkeiten vorstellen. So kann man unnötige Emails loswerden und sein Postfach schonen.

Das rss2pushover Script auf Github ermöglicht es einen RSS feed zu parsen und neue Einträge per pushover.net auf ein Endgerät pushen. Dabei wird eine kleine Datenbank eingesetzt um zu prüfen ob Einträge bereits verarbeitet wurden. Somit erhält man keine doppelten Nachrichten.

Beim Pushen der Nachrichten hat man mehrere Optionen angeben wie z.B. Sound, Wichtigkeit, Link etc.

Push Beispiel:


# send item to pushover.net
my $response = LWP::UserAgent->new()->post(
	"https://api.pushover.net/1/messages.json", [
	"token" => $PUSH_TOKEN,
	"user" => $PUSH_USER,
	"message" => $description,
	"title" => $title,
	"url" => $link,
	"url_title" => $title
]);

if ($response->is_success) {
	# push accepted
} else {
	# push not accepted
}

Einfacher kann man es nicht mehr machen. Bis jetzt sind die Nachrichten immer direkt und ohne merkbare Verzögerung angekommen. Mal schauen wo man das noch überall einbauen kann :)

dmesg mit Zeitangabe

Die dmesg Zeitangaben sind nicht wirklich zu lesen, aber manchmal braucht man sie dann doch eben. So einfach ist es dann doch wieder nicht:

# perl -e 'openf,"/proc/uptime";=~/\s/;$x=time-$`;for(qx{dmesg}){s/^\[\s*([\d.]+)\]\s+//;@t=(localtime($x+$1))[5,4,3,2,1,0];$t[0]+=1900;$t[1]+=1;printf"[%04d-%02d-%02d%02d:%02d:%02d] %s",@t,$_}'

MtGox Trader

Nachdem MtGox jetzt endgültig tot ist kann ich auch endlich mal meinen Trading Bot veröffentlichen. Eigentlich wollte ich das schon früher machen, aber bin noch nicht dazu gekommen.
Der Bot handelt nur wenn es auch einen Gewinn abwirft und somit kann man eigentlich nichts verlieren. Dadurch ist er natürlich sehr sehr langsam und meistens habe ich nur einen Trade pro Tag hinbekommen, aber dafür mit Gewinn.

Die Konfiguration ist nicht ganz einfach, weil man die sqlite Datenbank einmal per Hand befüllen muss. Wenn man Bitcoins kaufen will, muss man einen Eintrag in die Tabelle “sold” mit der Anzahl der Bitcoins und eines Preises füllen. Der Preis bestimmt wie niedrig der Preis des nächsten kaufes sein muss. Abhängig je nachdem wie hoch man die Gewinnschwelle einstellt.

Den Code gibt es auf github.com.

Wer nicht immer auf Logfiles lesen steht – es gibt auch ein kleines mini Webinterface dass die letzten Transkationen anzeigt und einen Graphen mit pchart erstellt.

WordPress XMLRCP API

Ich glaube die WordPress API ist einer der am wenigsten dokumentierten API die ich jemals gesehen habe. Deswegen gibt es jetzt ein Beispiel um in Perl ein Bild hochzuladen, einen Post zu erstellen mit Categories, Custom Fields und einem Featured Image.

#!/usr/bin/perl
# script: publish article to a wordpress blog using XMLRPC interface. Uploading a picture and setting this as a featured image. Additionally add custom fields.
# author: <bert2002>
use strict;
use utf8;
use XMLRPC::Lite;
use IO::Socket::SSL;
my ($buf,$contents);
my $pictureid;
my @categories;
# settings
my $username = “USERNAME”;
my $password = “PASWORT”;
my $server = “https://www.yourblog.com/xmlrpc.php”;
my $image = “PATHtoIMAGE”
my $htmlpost = “THErealCONTENT”;
# upload picture to wordpress
open(FILE, “$image”) or die “$!”;
while (read(FILE, $buf, 60*57)) {
        $contents .= $buf;
}
close(FILE);
my $res = XMLRPC::Lite
->proxy($server)
->call(‘metaWeblog.newMediaObject’, 1, $username, $password,
{ name => $image, type => ‘image/jpeg’, bits => $contents } )
->result;
if (defined ($res)) {
$pictureid = $res->{id};
print “. picture uploaded with id $pictureid\n”;
} else {
        print ” .. uploading picture failed: $!”;
}
# post article to wordpress
my $publishdate = “20100220T12:34:56”;
# prepare categories
my $multicategories = “cat1 cat2 cat3”;
@categories = split(/ /, $multicategories);
# finally create that fucking post
my $res = XMLRPC::Lite
->proxy($server)
->call(‘metaWeblog.newPost’, 1, $username, $password,
{
        categories => \@categories,
        custom_fields => [
                { “key” => “keyone”, “value” => “value one” },
                { “key” => “keytwo”, “value” => “value two” }
        ],
        description => $htmlpost,
        title => $productname,
# dateCreated => $publishdate,
        mt_allow_comments => 0,
        wp_post_thumbnail => $pictureid,
}, 1)->result;
if (defined ($res)) {
        print “. posted article id $res and picture id $pictureid\n”;
} else {
        print “.. posting article with id $res failed: $!”;
}
 oder auf gist.github.com

Twitter::Lite und OAuth

Wie manche früher oder später *hust* mitbekommen haben erlaubt Twitter jetzt nur noch OAuth als Authentifizierungsverfahren. Ich war in letzter Zeit irgendwie sehr beschäftigt und habe es erst gestern gemerkt. Also musste ich mein rss2twitter script auf OAuth umstellen und dabei hat bayashi sehr geholfen. Im großen und ganzen geht das sehr einfach und hier gibt es das Script zum Nachlesen:

#!/usr/bin/perl
# script: Using the latest RSS entry to update Twitter

use strict;
use warnings;
use Net::Twitter::Lite;
use LWP::Simple;
use XML::RSS::Parser::Lite;
use WWW::Shorten::Metamark;

my $feed = get(‘http://dailywadoku.itbert.de/feed.rss’);
my $rp = new XML::RSS::Parser::Lite;

$rp->parse($feed);

my $it = $rp->get(0);

my $long_url = $it->get(‘url’);
my $short_url = makeashorterlink($long_url);
my $message = $it->get(‘description’);

$message =~ s/^.+ – //; # remove dash seperator.
$message =~ s/^\s+//; # Nuke any leading space; every char counts.
$message =~ s/\s+$//; # Nuke any trailing space; every char counts.
$message =~ s/[_]+$//; # Nuke any trailing underscores; happens when message is short.

$message = substr $message , 0 , 116; # Twitter can only handle 140 chars.
$message .= ‘ -> ‘; # Append ellipse to denote further content available.
$message .= $short_url; # Append the shortened URL.

# get in http://dev.twitter.com/apps/XXXXXX
my %CONSUMER_TOKENS = (
consumer_key    => ‘** CONSUMER_KEY **’,
consumer_secret => ‘** CONSUMER_SECRET **’,);

# get in http://dev.twitter.com/apps/XXXXXX/my_token
my $ACCESS_TOKEN        = ‘** ACCESS_TOKEN **’;
my $ACCESS_TOKEN_SECRET = ‘** ACCESS_TOKEN_SECRET **’;

my $t = Net::Twitter::Lite->new(%CONSUMER_TOKENS);
$t->access_token($ACCESS_TOKEN);
$t->access_token_secret($ACCESS_TOKEN_SECRET);
my $status = $t->update($message);

So Sachen wie ** CONSUMER_KEY ** müssen natürlich ersetzt werden und sind hier nur Platzhalter.

Domain Name Check Script

Manchmal will man gaanz einfach und schnell einen Domainnamen mit mehreren Endungen testen. Ich bin gerade ein bisschen am perl basteln und habe ein kleines script dazu geschrieben.

Usage:

dnscheck.pl -H itbert

Output:

DOMAIN CHECK: itbert
=== AVAILABLE ===
itbert.com
itbert.org
itbert.net
=== UTILIZED ===
itbert.de

Wenn man noch die Option “-f” dranhaengt bekommt man auch alle schon benutzten Domains aufgelistet. Die zu ueberpruefenden Domainendungen kann man einfach in dem Script eintragen.