30 July 2016

Hide and Unhide Plex Media Servers Libraries

Plex media server is a famous media server, I use it at home to set local media server for myself and family.

However, to be able to hide some Libraries is not straightforward,  as it is not supported by the app itself, and there's a plugin that allows you to do so for 1 Library for free and pay for the others (It called Lock for Plex).

I used this extension and find out how it works, and I hacked it and be able to hide more than one Library.

How "Lock for Plex" work is by updating the database used by Plex.

It uses two bash files, one for lock and the other for unlock:


Plex Media Server/Plug-ins/Lock_for_Plex.bundle/Contents/Resources/lock_support/lock.sh

Plex Media Server/Plug-ins/Lock_for_Plex.bundle/Contents/Resources/lock_support/unlock.sh

Here's the content for myself after I've been modified on this file:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
cat lock.sh
#!/bin/bash


lockplex="UPDATE metadata_items SET metadata_type=20 WHERE library_section_id=2 and metadata_type=1; DELETE FROM library_sections WHERE id=2;"
lockplex2="UPDATE metadata_items SET metadata_type=4444 WHERE library_section_id=8 and metadata_type=4; DELETE FROM library_sections WHERE id=8;"

cd "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-ins/Lock_for_Plex.bundle/Contents/Resources/lock_support/"

./sqlite3 "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db" "$lockplex" 
./sqlite3 "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db" "$lockplex2" 

exit;
mhewedy@probook:~$ cat unlock.sh 
#!/bin/bash

unlockplex="UPDATE metadata_items SET metadata_type=1 WHERE library_section_id=2 and metadata_type=20; INSERT OR REPLACE INTO library_sections (id,name,section_type,language,agent,scanner,created_at,updated_at,scanned_at,user_fields,uuid) VALUES (2,'English Movies',1,'en','com.plexapp.agents.imdb','Plex Movie Scanner','2016-07-03 07:27:07','2016-07-03 08:35:21','2016-07-03 08:35:21','pr%3AenableCinemaTrailers=0&pr%3AincludeInGlobal=0','c07640f7-a137-4987-95ba-c3c5850383d3');"

unlockplex2="UPDATE metadata_items SET metadata_type=4 WHERE library_section_id=8 and metadata_type=4444; INSERT OR REPLACE INTO library_sections (id,name,section_type,language,agent,scanner,created_at,updated_at,scanned_at,user_fields,uuid) VALUES (8,'TV Shows',2,'en','com.plexapp.agents.thetvdb','Plex Movie Scanner','2016-07-07 03:45:33','2016-07-07 03:45:55','2016-07-13 21:03:02','pr%3AincludeInGlobal=0','0d670ea9-0da4-4639-8f52-2fcd64f3d8c8');"

cd "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-ins/Lock_for_Plex.bundle/Contents/Resources/lock_support/"

./sqlite3 "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db" "$unlockplex" 
./sqlite3 "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db" "$unlockplex2" 

exit;

One other way to achieve the same result is to have some other disk partition and mount it on-demond.


26 July 2016

Create Local git server

Actually git doesn't work with client-server concept, it is distributed source control, where any repo can act as a remote repo for others and in the same time a local repo.

But in your organization, you need to have a place where you have your code resides either for keep code save, or even to do automated deployment or for any other reason.

suppose you have 2 Linux machines, machine A and machine B. (machine A will act like a server, where machine B will be your development machine)

1. machine A have to have ssh server installed; Login to machine A with user say 'git':

ssh git@machine_a

2. go to a directory where you want to keep your code, or even you want to do the autodeployemnt from there

sudo mkdir -p /repos/test-repo
sudo chown -R git:git /repos/rest-repo

3. init the origin on the server

cd /repos/test-repo
git init --bare

4. Your server is ready now, Now go to the client machine and create a folder where you will put your development source code:

cd ~/my-test-repo-code

5. create local git repo and point to the remote server we just created

git init
git remote add origin git@machine_a:/repos/test-repo

6. test your installation:

# we still in the client machine
touch test-file.txt
git add test-file.txt
git commit -a -m 'init'
git push remote origin

7. that's it, you now can write code and push it to your server, you can add hocks on the server (for deployment) or install your a web server to show the code in fancy interface or support other activities like code-review, etc.

Have fun.

24 July 2016

Tail Recursion in Nodejs

I've talked about tail recursion in a previous post, today I'll show an example on nodejs.

We have a function that sums numbers starting from 0 to an n number.

We have both version of it, the tail recursion and non-tail recursion version:
1
2
3
4
5
6
7
8
function sumNonTailVersion(n) {
    return (n < 1) ? 0 : n + sumNonTailVersion(n - 1);
}

function sumTailVersion(n, acc) {
    acc = acc || 0;
    return (n < 1) ? acc : sumTailVersion(n - 1, acc + n);
}

Use the following code to test the above two functions:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
try {
    console.log('sumNonTailVersion: ', sumNonTailVersion(1000000));
} catch (e) {
    console.error('sumNonTailVersion: ', e.message);
}
try {
    console.log('sumTailVersion: ', sumTailVersion(1000000));
} catch (e) {
    console.error('sumTailVersion: ', e.message);
}

Run the functions using the following flags:
node --use-strict --harmony-tailcalls file.js

And here's the result:
1
2
sumNonTailVersion:  Maximum call stack size exceeded
sumTailVersion:  500000500000

The non-tail recursion version fail with "Maximum call stack size exceeded"

Note, if we run without the flags "--use-strict --harmony-tailcalls" the nodejs will run without tail recursion optimizations, and both will treated the same (will through the same error above).


02 July 2016

Reduction Operation in functional programming

the operation "Reduce" or "Fold" is a very important operation in functional programming, as you could implement all other operations using the reduce operation. (see ProgFun course at Coursera)

Also, Java tutorial has a very straightforward illustration for Reduction in Java 8: https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html

I want to talk about a case (from cobone-reviews project) that I needed low-level reduction operation.

First I have a Map<Object, List<Long>> that looks like:

{"dp.g.doubleclick.net": [0,1,0,0,0],"cobonereviews.tk": [0,1,0,0,0],"www.facebook.com": [3,4,0,0,0],"www.google.co.in": [0,1,0,0,0],"localhost:8080": [0,0,40,5,3],"l.facebook.com": [0,1,0,0,0],"www.google.com": [0,10,5,0,0],"www.google.com.sa": [0,11,0,0,0],"www.google.com.hk": [0,1,0,0,0],"www.google.ae": [0,3,0,0,0]}
I need to group each top private domain's result together, So the result would looks like:
 {  
   "localhost:8080":[  
    0,  
    0,  
    40,  
    5,  
    3  
   ],  
   "facebook":[  
    3,  
    5,  
    0,  
    0,  
    0  
   ],  
   "google":[  
    0,  
    26,  
    5,  
    0,  
    0  
   ],  
   "cobonereviews":[  
    0,  
    1,  
    0,  
    0,  
    0  
   ],  
   "doubleclick":[  
    0,  
    1,  
    0,  
    0,  
    0  
   ]  
 }  
So first I used the following method to get Top Private Domain from the Map's keys above:
 // Example: www.google.com.sa, google.com, google.eg all translated to  
 // google  
 private String getDomainName(Object referrer) {  
      try {  
           String topPrivateDomain = InternetDomainName.from(referrer.toString()).topPrivateDomain().name();  
           String publicSuffix = InternetDomainName.from(referrer.toString()).publicSuffix().name();  
           String onlyDomainName = topPrivateDomain.replace(publicSuffix, "");  
           return onlyDomainName.endsWith(".") ? onlyDomainName.substring(0, onlyDomainName.length() - 1)  
                     : onlyDomainName;  
      } catch (Exception ex) {  
           log.error(ex.getMessage());  
           return referrer.toString();  
      }  
 }  
Then, I need to use the getDomainName method above as a grouping key and then for the values, I need to concatenate the all lists under the same domain together, for example for case of facebook, I have the following map:
 "www.facebook.com":[   
  3,   
  4,   
  0,   
  0,   
  0   
  ], "l.facebook.com":[   
  0,   
  1,   
  0,   
  0,   
  0   
 ] 
And I need the result to be:

 "facebook":[   
  3,   
  5,   
  0,   
  0,   
  0   
  ]  
So, The reduction method that do the the concat operation looks like:
 collect2.entrySet().stream().collect(groupingBy(e -> getDomainName(e.getKey()),  
  reducing(new ArrayList<Long>(), e -> e.getValue(), (l1, l2) -> accumlateLists(l1, l2))));  
And here's the implementation of accumlateLists method
 private List<Long> accumlateLists(List<Long> accumlator, List<Long> list) {  
      if (accumlator.isEmpty()) {  
           return list;  
      } else {  
           for (int i = 0; i < accumlator.size(); i++) {  
                accumlator.set(i, accumlator.get(i) + list.get(i));  
           }  
           return accumlator;  
      }  
 }  
Note, In the reduction method above, we used the form:
 reducing(U identity, Function<? super T, ? extends U> mapper, BinaryOperator<U> op)  
The first parameter is the accumulator and the zero value (empty ArrayList), the second parameter is mapper, which maps the Entry object to List<Long> which is the object that will be used by the third parameter, hence the mapper Function returns object of type U the same that would be used as type parameter for the BinaryOperator (which is a BiFunction).

Complete source code would be found in this file.

04 March 2016

Why logging frameworks did not make use of Java 8 like JUL did

1)
In scala the language, there's three types of value definition; regular variables that are initialized once reached by the execution environment like:

val x: Int = getXValueFromDatabase()

the function getXValueFromDatabase()will be executed once this line is reached.

The second type is lazy variables, the will not be evaluated until the variable is used, and the syntax like:

lazy val x: Int = getXValueFromDatabase()

The third type is defined like functions (actually there are functions) and defined using the function definition syntax like:

def x: Int = getXValueFromDatabase()

and will be evaluated each time the symbol x is referred.
see this SO question: http://stackoverflow.com/q/9449474

2)
In the java world, there's variables like the first type in scala and methods like the third type in scala, and also there's Initialization-on-demand holder idiom

The most common used is the variables and methods.

So, how can we use it in Logging?

Look to the javadoc from sfl4j
void info(String format,
        Object... arguments)
Log a message at the INFO level according to the specified format and arguments.
This form avoids superfluous string concatenation when the logger is disabled for the INFO level. 
What it can do for you is that it defers the string concatenation until the framework do a check like the following:

 if (!isLoggable(level)) {
     return;
 }

but this is not enough, calling external service/resource to get the information to log is resource wasting when the log level is higher than the one specified in the application.

So, can we make use of lazy or even function calls here, where the logging peace of data is not calculated until the check of (isLoggable) is done?

Yes, JUL did it, using Java8 Supplier interface

Look to this example:

package test;

import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;

public class LoggingExample {

    public static void main(String[] args) throws Exception {
        Logger logger = Logger.getGlobal();
        logger.addHandler(new FileHandler(System.getenv("HOME") + "/logging_example.log"));

        logger.setLevel(Level.INFO);

        logger.fine(() -> String.format("V1 - the value of the expensive resource is \"%s\"",
                getSomeExpensiveResourceListExternalServiceCall("V1")));

        logger.fine(String.format("V2 - the value of the expensive resource is \"%s\"",
                getSomeExpensiveResourceListExternalServiceCall("V2")));

        logger.info(() -> String.format("V3 - the value of the expensive resource is \"%s\"",
                getSomeExpensiveResourceListExternalServiceCall("V3")));

        logger.info(String.format("V4 - the value of the expensive resource is \"%s\"",
                getSomeExpensiveResourceListExternalServiceCall("V4")));
    }

    private static Object getSomeExpensiveResourceListExternalServiceCall(String version) {
        System.out.println(version + " - GETTING THE EXPENSIVE RESOURCE");
        return "some expensive resource";
    }
}

I run this example with setting the logger level to info (as shown) and here's the std out:

V2 - GETTING THE EXPENSIVE RESOURCE
V3 - GETTING THE EXPENSIVE RESOURCE
V4 - GETTING THE EXPENSIVE RESOURCE

Not that, V1 does not call the getSomeExpensiveResourceListExternalServiceCall at all.
This is because the supplier will never be executed until the following check is done:

 if (!isLoggable(level)) {
     return;
 }

This is a good usage of Java 8, and every single logging framework should make use of it.

29 February 2016

Scala or Kotlin

JVM has many language based on it, many of them are famous like Groovy, Scala, Koltin and others.

In the past I've played with Scala, now I try to post the same code snippet in Scala and in Koltin (actually koltin looks like scala in many ways):

Scala Code:

// scala

object Main {
  def main(args: Array[String]): Unit = {

    val a = 10
    val b = 50
    println(apply(a, b, { (x, y) => x * y }))
    println(apply(a, b, sum))

    val l = List(1, 3, 5)
    l map { _ * 2 } filter { _ > 4 } foreach { println(_) }
  }

  def sum(a: Int, b: Int): Int = a + b

  def apply(x: Int, y: Int, f: (Int, Int) => Int) = f(x, y)
}

Koltin Code:
// kotlin

fun main(args: Array<String>): Unit {

    val a = 10
    val b = 50
    println(apply(a, b, {x, y -> x * y}))
    println(apply(a, b, ::sum))

    val l = listOf(1, 3, 5)
    l.map { it * 2 } .filter { it > 4 } .forEach { println( it ) }
}


fun sum(a: Int, b: Int): Int = a + b

fun apply(x: Int, y: Int, f: (Int, Int)-> Int) = f(x, y)


16 January 2016

Html5Mode in angular js for Java

Here's a sample Servlet filter implementation to allow return pages from the server with the / pattern.

Note: I've marked angularjs requests with "source" header set to "ng".

@WebFilter(urlPatterns = { "/*" })
public class Html5ModeFilter implements Filter {

@Override
public void destroy() {

}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {

HttpServletRequest request = ((HttpServletRequest) req);
boolean notNgRequest = !"ng".equalsIgnoreCase(request.getHeader("source"));
String servletPath = request.getServletPath();

if (notNgRequest && !servletPath.contains(".")) { // skip .js, .css,
// .png, etc...
if (!"/".equalsIgnoreCase(servletPath)) {
((HttpServletResponse) res).sendRedirect("/?next=" + servletPath.substring(1));
return;
}
}

chain.doFilter(req, res);
}

@Override
public void init(FilterConfig arg0) throws ServletException {

}


}