Entries tagged github

PHP Commandline Notification

Posted on 3. Januar 2018 Comments

When you run long (PHP) jobs it’s easy to forget about the terminal. That’s why I’ve created a small PHP package that will make a little sound. Because PHP itself doesn’t have this functionality anymore it’s possible to just echo the ASCII sign for BEL. Simply put this at the end of your PHP job:

use repat\CommandlineBell;
// flashes screen if possible, otherwise just bell()
CommandlineBell::flash();
// makes a beep sound
CommandlineBell::bell();

Under the hood it’s really just:
echo "0x07";

A good (non-PHP) alternative I found is brb by Viktor Fröberg, just run commands like this

php artisan migrate --seed ; brb

Of course it’s always possible to just run a TTS app on the commandline via exec() like this:

exec("say terminal task done");

Or you could do it similar to brb:

php artisan migrate --seed ; say seeding done

Source on GitHub

Quick and dirty redirect script for the fitting shipping provider

Posted on 2. März 2017 Comments

Another way to use the PHP library shipping-service-provider-check apart from fixing the shipping providers in the ERP Plentymarkets is a simple quick and dirty PHP script that redirects to the tracking page of a fitting shipping provider. You can find the whole sourcecode on GitHub.

Installation

If you don’t use some sort of MVC this is a quick way to do it. If you do, I suspect you’ll know how to alter this example to fit your system. Feel free to write me an e-mail or comment if you need help

  1. Log onto your server and create a folder
  2. Copy or git pull the files, including .htaccess
  3. Get Composer
  4. composer require repat/shipping-service-provider-check

Explanation of the code

The $trackingId variable is received via HTTP GET. This means the URL would be http://url.tld/trackingscriptfolder/script.php?tracking_id=123456 (or without the script.php in case of the .htaccess), where 123456 is the TrackingID. The rest is more or less just for debugging. The scripts returns a HTTP Code 422 and ends if there is no input given.

$trackingId = $_GET["tracking_id"];
if (empty($trackingId)) {
  $unprocessableEntity = 422;
  http_response_code($unprocessableEntity);
  echo "wrong input";
  return;
}

Next the URLs will be defined. The keys have to match the shipping providers so make sure the shipping providers are added at the library as well. The TrackingID will be added at the end of the URL, so make sure they have the right format.

$shippingProviderURLs = [
  "dhl" => 'https://nolp.dhl.de/nextt-online-public/set_identcodes.do?idc=',
...
];

Then follows the documented way of checking for the providers. It could technically be that at the same time a TrackingID is valid for more than one provider. To keep things simple, we’ll just use the first one (array_search instead of array_keys). In case there is none found, array_search returns false and the script continues. In case there is one found, the header() function is called to redirect the user to the correct provider page.

$checkedProvider = array_search(true, $result);
$urlOfCheckedProvider = $shippingProviderURLs[$checkedProvider];

if ($checkedProvider !== false) {
  header('location: ' . $urlOfCheckedProvider . $trackingId);
}

Now it’s up to you what you will do with the ones you can’t redirect. I decided to write a little skeleton.html file and include that with a simple message that the user could try the shipping providers where a check is not possible (no API, no website scraping, no regex). They are listed earlier:

$shippingProviderURLsNoCheck = [
  "DPD" => 'https://tracking.dpd.de/parcelstatus?query=',
...

Markdown Templates for README files on GitHub

Posted on 7. März 2014 Comments

Every time I upload a new project on GitHub I find myself writing almost an identicially structured README.md file in Markdown. So I thought I could make some templates for the next times. Right now I only have one for mobile apps and websites with GitHub Pages, but there’s more to come.

Also I found that quite a lot of projects have very unstructured and ugly READMEs. It’s always nice to get a quick overview over a project, especially when they don’t have a website. So maybe someone can use this.

How to compile async for scala with sbt

Posted on 6. Dezember 2013 Comments

SBT is the build tool for Scala, much like Maven or Ant is for Java. Scalas async library uses it for compiling. You could just it from the source or compile it into a handy .jar file. That’s where SBT comes in. The Scala version I used it 2.10.3, SBT in version 0.13.0 and async in 0.9.0. The build.sh in the repository didn’t work for me.

Clone the lastest version of the GitHub repository: https://github.com/scala/async

git clone https://github.com/scala/async.git

Then download and install sbt from scala-sbt.org. For Ubuntu 12.04 I just used the .deb package.

wget http://repo.scala-sbt.org/scalasbt/sbt-native-packages/org/scala-sbt/sbt/0.13.0/sbt.deb

And install it.

sudo dpkg -i sbt.deb

Then open it in the same folder you cloned the git repository:

repat@laptop:~/asynctest/async$ sbt
Loading /usr/share/sbt/bin/sbt-launch-lib.bash
[info] Loading project definition from /home/repat/asynctest/async/project
[info] Updating {file:/home/repat/asynctest/async/project/}async-build...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Set current project to scala-async (in build file:/home/repat/asynctest/async/)
>

Maybe a couple of updates will appear here and depending on your internet connection it might actually take a while.
Once you get the > sign type compile and this will happen:

[info] Updating {file:/home/repat/asynctest/async/}async...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 15 Scala sources to /home/repat/asynctest/async/target/scala-2.10/classes...
[warn] there were 2 feature warning(s); re-run with -feature for details
[warn] one warning found
[success] Total time: 28 s, completed 06.12.2013 19:22:09

You will now have the compiled .class files in …/async/target/scala-2.10. The get the .jar do the following.

> publish
[info] Packaging /home/repat/asynctest/async/target/scala-2.10/scala-async_2.10-0.9.0-SNAPSHOT-sources.jar ...
[info] Done packaging.
[info] Wrote /home/repat/asynctest/async/target/scala-2.10/scala-async_2.10-0.9.0-SNAPSHOT.pom
[info] :: delivering :: org.scala-lang.modules#scala-async_2.10;0.9.0-SNAPSHOT :: 0.9.0-SNAPSHOT :: integration :: Fri Dec 06 19:25:16 CET 2013
[info] 	delivering ivy file to /home/repat/asynctest/async/target/scala-2.10/ivy-0.9.0-SNAPSHOT.xml
[info] Main Scala API documentation to /home/repat/asynctest/async/target/scala-2.10/api...
[warn] there were 2 feature warning(s); re-run with -feature for details
model contains 29 documentable templates
[warn] /home/repat/asynctest/async/src/main/scala/scala/async/Async.scala:11: Could not find any member to link for "scala.concurrent.Future".
[warn] /**
[warn] ^
[warn] /home/repat/asynctest/async/src/main/scala/scala/async/internal/FutureSystem.scala:9: Could not find any member to link for "scala.async.AsyncBase".
[warn] /**
[warn] ^
[warn] three warnings found
[info] Main Scala API documentation successful.
[info] Packaging /home/repat/asynctest/async/target/scala-2.10/scala-async_2.10-0.9.0-SNAPSHOT-javadoc.jar ...
[info] Done packaging.
[trace] Stack trace suppressed: run last *:publish for the full output.
[error] (*:publish) java.io.IOException: Access to URL https://oss.sonatype.org/content/repositories/snapshots/org/scala-lang/modules/scala-async_2.10/0.9.0-SNAPSHOT/scala-async_2.10-0.9.0-SNAPSHOT.pom was refused by the server: Unauthorized
[error] Total time: 12 s, completed 06.12.2013 19:25:27

I’m not sure why it stops with an error here or rather, why access is denied to that repository. Anyway, the scala-async_2.10-0.9.0-SNAPSHOT.jar file is now in …/async/target/scala-2.10.

As mentioned in the error message, you get the stacktrace with last *:publish. I leave this here so people can find it via google.

last *:publish 
java.io.IOException: Access to URL https://oss.sonatype.org/content/repositories/snapshots/org/scala-lang/modules/scala-async_2.10/0.9.0-SNAPSHOT/scala-async_2.10-0.9.0-SNAPSHOT.pom was refused by the server: Unauthorized
	at org.apache.ivy.util.url.AbstractURLHandler.validatePutStatusCode(AbstractURLHandler.java:79)
	at org.apache.ivy.util.url.BasicURLHandler.upload(BasicURLHandler.java:231)
	at org.apache.ivy.util.FileUtil.copy(FileUtil.java:150)
	at org.apache.ivy.plugins.repository.url.URLRepository.put(URLRepository.java:84)
	at org.apache.ivy.plugins.repository.AbstractRepository.put(AbstractRepository.java:130)
	at org.apache.ivy.plugins.resolver.RepositoryResolver.put(RepositoryResolver.java:234)
	at org.apache.ivy.plugins.resolver.RepositoryResolver.publish(RepositoryResolver.java:216)
	at sbt.IvyActions$$anonfun$publish$3.apply(IvyActions.scala:258)
	at sbt.IvyActions$$anonfun$publish$3.apply(IvyActions.scala:257)
	at scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:772)
	at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
	at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47)
	at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:771)
	at sbt.IvyActions$.publish(IvyActions.scala:257)
	at sbt.IvyActions$$anonfun$publish$1$$anonfun$apply$1.apply$mcV$sp(IvyActions.scala:93)
	at sbt.IvyActions$$anonfun$publish$1$$anonfun$apply$1.apply(IvyActions.scala:93)
	at sbt.IvyActions$$anonfun$publish$1$$anonfun$apply$1.apply(IvyActions.scala:93)
	at sbt.IvyActions$.withChecksums(IvyActions.scala:102)
	at sbt.IvyActions$.sbt$IvyActions$$withChecksums(IvyActions.scala:97)
	at sbt.IvyActions$$anonfun$publish$1.apply(IvyActions.scala:93)
	at sbt.IvyActions$$anonfun$publish$1.apply(IvyActions.scala:87)
	at sbt.IvySbt$Module$$anonfun$withModule$1.apply(Ivy.scala:116)
	at sbt.IvySbt$Module$$anonfun$withModule$1.apply(Ivy.scala:116)
	at sbt.IvySbt$$anonfun$withIvy$1.apply(Ivy.scala:104)
	at sbt.IvySbt.sbt$IvySbt$$action$1(Ivy.scala:51)
	at sbt.IvySbt$$anon$3.call(Ivy.scala:60)
	at xsbt.boot.Locks$GlobalLock.withChannel$1(Locks.scala:98)
	at xsbt.boot.Locks$GlobalLock.xsbt$boot$Locks$GlobalLock$$withChannelRetries$1(Locks.scala:81)
	at xsbt.boot.Locks$GlobalLock$$anonfun$withFileLock$1.apply(Locks.scala:102)
	at xsbt.boot.Using$.withResource(Using.scala:11)
	at xsbt.boot.Using$.apply(Using.scala:10)
	at xsbt.boot.Locks$GlobalLock.ignoringDeadlockAvoided(Locks.scala:62)
	at xsbt.boot.Locks$GlobalLock.withLock(Locks.scala:52)
	at xsbt.boot.Locks$.apply0(Locks.scala:31)
	at xsbt.boot.Locks$.apply(Locks.scala:28)
	at sbt.IvySbt.withDefaultLogger(Ivy.scala:60)
	at sbt.IvySbt.withIvy(Ivy.scala:101)
	at sbt.IvySbt.withIvy(Ivy.scala:97)
	at sbt.IvySbt$Module.withModule(Ivy.scala:116)
	at sbt.IvyActions$.publish(IvyActions.scala:87)
	at sbt.Classpaths$$anonfun$publishTask$1.apply(Defaults.scala:1094)
	at sbt.Classpaths$$anonfun$publishTask$1.apply(Defaults.scala:1093)
	at scala.Function3$$anonfun$tupled$1.apply(Function3.scala:35)
	at scala.Function3$$anonfun$tupled$1.apply(Function3.scala:34)
	at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47)
	at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:42)
	at sbt.std.Transform$$anon$4.work(System.scala:64)
	at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
	at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237)
	at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
	at sbt.Execute.work(Execute.scala:244)
	at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
	at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237)
	at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:160)
	at sbt.CompletionService$$anon$2.call(CompletionService.scala:30)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
	at java.util.concurrent.FutureTask.run(FutureTask.java:166)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
	at java.util.concurrent.FutureTask.run(FutureTask.java:166)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:724)
[error] (*:publish) java.io.IOException: Access to URL https://oss.sonatype.org/content/repositories/snapshots/org/scala-lang/modules/scala-async_2.10/0.9.0-SNAPSHOT/scala-async_2.10-0.9.0-SNAPSHOT.pom was refused by the server: Unauthorized

Updating Owncloud News App with cron and Uberspace

Posted on 27. November 2013 Comments

Since it’s not possible to create a cronjob with the user the webserver is running under(as advised), I just created a cronjob with my user(crontab -e) and it works just fine.

[repat@uberspace]$ crontab -l
*/15 * * * * /package/host/localhost/php/bin/php -f /home/repat/html/owncloud/cron.php

The problem was the following: owncloud wouldn’t update my news and I didn’t think it was a cron problem, since I couldn’t update it manually(AJAX). Adding new feeds however did work. I still don’t get why manual updating doesn’t work , even with the Android app. Opening cron.php in the webbrowser didn’t work, although it did display {„status“:“success“}..turns out: it has to be called via CLI.

Unfortunately, I get an email every 15 minutes now… To disable that I added this above the cron entry:

MAILTO=""

Thanks to Raydiation and j-ed for helping me.

Simple MRBS Output from Database

Posted on 17. September 2013 Comments

I wrote a little PHP-script that extracts the most important and current data from MRBS’s MySQL database and just prints them in a simple HTML file. Its not pretty but good for bandwith and clarity. We use it to display information on an energy efficient e-ink screen in front of conference/computer rooms.

$date is set like this:

$date = date("Y-m-d");

The SELECT-statements go like this, where N is the ID of the room(in the database, not what you might call it)

SELECT name,description,from_unixtime(start_time),from_unixtime(end_time) FROM mrbs_entry WHERE from_unixtime(start_time) LIKE '%" . $date . "%' AND room_id = N;

I’m not gonna explain here how to establish a database connection in PHP, but you can have a  look at the whole sourcecode at github 😉

I then cut off the date with substr() because it’s always 10 characters in front of time->(YYYY-MM-DD) and printed it via echo. This is the simple version, there is a version with tables on github.

while($row=mysql_fetch_row($qry01)) {
echo "- <strong>Room</strong> 01 | <strong>Desc:</strong>" . $row[0]." - ".$row[1]." |  <strong>Time:</strong> ". substr($row[2],10) . " - " . substr($row[3],10) . " <br />";
}

update: I wrote another version that prints JSON objects which can be parsed on the other side. For easier parsing(e.g. if everything is in one String) I numbered them:

$jsonarray = array('begin' . $i => substr($row[2],11, 5), 'end' . $i => substr($row[3],11,5), 'name' . $i => $row['name'], 'description' . $i =>  $row['description']);

You’ll find the whole thing on github.