megacolorboy

Abdush Shakoor's Weblog

Writings, experiments & ideas.

Configuring audio drivers in Arch Linux

Yesterday, I thought of testing my Arch Linux system's audio and turns out, I didn't even install it yet! ๐Ÿ˜’

Well, thanks to ArchWiki, it was simple enough to install to make the audio work on my old laptop. Just install the following packages:

pacman -S alsa-firmware alsa-lib alsa-utils

Reboot the system once you're done installing the packages. Depending on your window manager, you should be able to see your sound icon being active.

Bonus: Bash script to control your volume from the terminal

In my current laptop, I still haven't mapped out the keys to control the audio volume, so I thought of writing a small method in my .bashrc file, so that I can control it from my terminal.

Open your favorite text editor and Add this method in your .bashrc file:

# simple volume control
volume(){
    x=5
    if [ $1 == 'up' ]
    then
        amixer set Master $x%+ &> /dev/null
    elif [ $1 == 'down' ]
    then
        amixer set Master $x%- &> /dev/null
    elif [ $1 == 'toggle' ]
    then
        amixer set Master toggle &> /dev/null
    fi
}

Save the file, close your edit and refresh your file by typing:

source .bashrc

Now, it should work when you type any of these commands:

volume up
volume down
volume toggle

Hope this tiny script helps you out!

Troubleshoot time-related SSL errors on secure websites

As I was configuring Arch Linux setup on my old HP 8460p laptop, I noticed that I wasn't able to access any site using Chrome or Firefox as I was faced with a weird error:

I was quite confused and thought it might be an issue with my WiFi card or probably some server issue but turns out it was neither of them.

On the side of my screen, I noticed my system time was displaying 4 hours ahead of the current local time, which is wrong. So, I did a little research and turns out my suspicions were correct, it's a time-related issue.

How is time related to secure websites?

Well, each website that uses SSL or that begins with https:// are only valid for a period of time before getting expired. If the website that you're trying to visit presents a certificate with a time and date that doesn't match with your system's clock, Firefox will prevent you from accessing the page.

How to fix it?

Actually, the fix is quite simple. All you have to is just set the correct date and time on your system and you're good to go!

If you're using Linux, just do the following:

1. Set up your timezone

You can look up for your timezones by executing the following:

timedatectl list-timezones | less

Once, you've found your timezone, execute the following by replacing Continent/Country with your timezone:

timedatectl set-timezone Continent/Country

2. Manually set your local time

Execute the following to set up your time, locally on your system:

timedatectl set-time "yyyy-MM-dd hh:mm:ss"

3. Set the hardware clock from the system clock

The following command sets the hardware clock from the system clock:

hwclock --systohc

Now, that you've executed them, you should be able to view the correct time on your system by executing timedatectl status and you should see something like this:

               Local time: Sun 2020-06-14 21:04:04 +04
           Universal time: Sun 2020-06-14 17:04:04 UTC
                 RTC time: Sun 2020-06-14 17:04:05    
                Time zone: Asia/Dubai (+04, +0400)    
System clock synchronized: no                         
              NTP service: inactive 

Although, this issue was time-related, you may face the same kind of error for various other reasons. Try reading more on how to troubleshoot errors like these from Mozilla's official documentation.

Transfer files remotely using SCP

Do you want to transfer files remotely from one UNIX-based system to another? Try using the scp tool, which is a shorthand for Secure Copy Protocol. It's based off the SSH protocol using it as a means to securely transfer files from a local machine to one or more remote machines.

Here's a code snippet that can help you out to transfer from computer A to computer B:

scp your_local_file user@ipaddress:/directory_to_store

And transfer from computer B to computer A:

scp user@ipaddress:/directory/file_name your_local_directory

Oh, before you transfer files to another computer, make sure that you have permissions to access it first. If you don't have one, then create a new account using useradd on your remote system.

How to manually configure your WiFi on Arch Linux?

Recently, I thought of playing around with Arch Linux to learn more about Linux under-the-hood and to see if it can become my new daily driver.

As I booted from live USB, I tried connecting to my WiFi using wifi-menu but it never worked after selecting my network name and entering the credentials.

So, I did a little bit of research in ArchWiki and forums and I figured a way to set it up manually using netctl by myself.

netctl is a network profile manager and it's apparently an Arch Linux project.

1. Select your interface

Before you begin to set up your WiFi connection from your computer, check if your network interface is being detected:

iwconfig

Since it's a WiFi connection, your interface most probably must be wlan0. If you see it, then set the interface up:

ip link set wlan0 up

2. Scan for networks

Now, that your interface, use it to scan for your WiFi network:

iwlist wlan0 scan | less

Once, you execute this command, you must be able to see your WiFi's SSID (or network name).

Now, put your interface down for a while:

ip link set wlan0 down

3. Create a network profile

Alright, go to /etc/netctl/examples/ directory and make a copy of the wireless-wpa file to the /etc/netctl directory:

cd /etc/netctl/examples
cp /etc/netctl/examples/wireless-wpa /etc/netctl/your-wifi-name

Now, go back to /etc/netctl/ directory and open the your-wifi-name file with your preferred text editor and edit the following only:

ESSID: your-wifi-name
key: your-wifi-password

After you're done editing, save the file.

4. Test network profile

To test if your profile is working, do the following:

netctl start your-wifi-name
ping -c 3 www.google.com

In case, you get an error, try doing this:

ip link set dev wlan0 down
netctl start your-wifi-name
ping -c 3 www.google.com

If you're able to ping, then it works. Else, edit your network profile and try connecting to it again.

5. Enable network profile

If you've reached this stage that means your network profile must be working fine. Just do the following to enable the network profile to run the internet throughout the setup:

netctl enable your-wifi-name

Try reading more about using netctl in Arch Linux's official wikipage.

Add search functionality to your static site

If you have a static site or a blog generated using a static-site generator but want to add a simple search functionality? This could be of your interest.

I'll take you through an example on how to build a simple search engine using a JSON file and AJAX requests.

1. Generate a JSON dump of your site

Although, it's not a database but it can act as an alternative to having one. Your JSON dump can contain any metadata that you wanted your users to search in your site. In my case, I thought of allowing the user to search title and category.

Is your site generated using Python and want to create a JSON dump? Read this article for more information.

2. Build search functionality

I won't go through the aspects of UI design in this article as I feel that it's subjective and depends on one's preferences but let's keep it simple enough for this tutorial.

Before you begin writing the function, place this component in your HTML template:

<div class="searchbox">
    <input id="searchinput" type="text">
    <div id="searchresults">
        <ul></ul>
    </div>
</div>

Anyway, here's the function and you can place it directly on your template or in a separate .js file:

var _url = "path-of-your-file.json";

$(document).ready(function(){
    $('#searchinput').keyup(function(e){
        var keyword = $(this).val();
        var code = e.keyCode ? e.keyCode : e.which;

        if(code == 13){
            $.ajax({
                url: _url,
                type: "GET",
                async: false,
            }).done(function(data){
                var results = "";
                if(data.articles.length > 0){
                    $.each(data.articles, function(key, value){
                        if(v.title.search(pattern) != -1 || v.category.search(pattern) != -1){
                            results += `<li><a href="${v.slug}">${v.title}</a></li>`;
                        }
                    });
                    $("#searchresults ul").html(results);
                }
            });
        }
    });
});

That's it! Now, when you execute your script, you should be able to view your search results just like as if it were using a database.

If you want to make it similar to mine, please feel free to inspect the code on the browser or go to my repository to see how it works.

Read and Write JSON to a file in Python

You can make use of the built-in json package in Python to read and write JSON data to a file.

Writing JSON to a file

You can store the information in a dictionary or dict object, which can contain any type of data like integers, booleans, arrays or nested objects.

By using a dict object, the json package will transform your dictionary into a serialized JSON string.

import json

dataObj = {}
dataObj['posts'] = []
dataObj['posts'].append({
    'title': 'Hello world',
    'category': 'Introduction',
    'slug': 'hello-world'
})

with open('data.json', 'w') as file:
    json.dump(dataObj, file)

Reading JSON from a file

Reading is as easy as writing to a file. Using the same package again, we can parse the JSON string directly from the file.

import json

with open('data.json', 'r') as file:
    data = json.load(file)
    for item in data['posts']:
        print 'Title: ' + item['title']
        print 'Category: ' + item['category']
        print 'Slug: ' + item['slug']

I read about different package alternatives like simplejson but I guess for now, this is a great way to get started especially, if you're working with web applications and are interacting with a serialized JSON data on a daily basis.

Build a menu tree using recursion

Hmm, what is the most efficient way to build a menu tree? ๐Ÿ˜…

Most people would go for a brute force solution if it's a straightforward menu but would that be possible if we intend to create multiple levels of menu items?

Sure, you could but as the number of loops increases, the complexity of time increases too. Not to forget, you'll end up writing code that'll look messy and unscalable.

I always loved the idea and simplicity of using recursion. So, I thought of exercising my recursion skills by writing a method that can generate a dynamic menu with x number of parent and child menu items.

The following example is written in PHP:

<?php
class FooController extends Controller {
    protected $menuHTML = "";

    private function menuItems() {
        return [
            [
                'title' => 'Item 1',
                'link' => '/item-1'
            ],
            [
                'title' => 'Item 2',
                'link' => '/item-2',
                'child_items' => [
                    [
                       'title' => 'Item 2.1',
                       'link' => '/item-2.1'
                    ],       
                    [
                        'title' => 'Item 2.2',
                        'link' => '/item-2.2'
                    ],       
                ]
            ],
            [
                'title' => 'Item 3',
                'link' => '/item-3'
            ],
            [
                'title' => 'Item 4',
                'link' => '/item-4'
            ],
        ];
    }

    // Build a menu tree
    private function buildMenu($menu) {
        foreach($menu as $menuItem){
            $this->menuHTML .= '<li class="item">';
            $this->menuHTML .= '<a href="'.$menuItem['link'].'">'.$menuItem['title'].'</a>';

            // Check if it has any child items
            if(array_key_exists("child_items", $menuItem){
                $this->menuHTML .= '<ul class="submenu">';
                $this->buildMenu($menuItem['child_items']);
                $this->menuHTML .= '</ul>';
            }

            $this->menuHTML .= '</li>'
        }
    }

    // Return the complete menu
    private function getMenu($menu) {
        $this->buildMenu($menu);
        return '<ul class="mainmenu">'.$this->menuHTML.'</ul>';
    }

    public function __construct() {
        pre($this->getMenu($this->menuItems());
        die;
    }
}
?>

Once you run it, you'll see something like this:

<ul class="mainmenu">
    <li class="item"><a href="/item-1">Item 1</a></li>
    <li class="item"><a href="/item-2">Item 2</a>
        <ul class="submenu">
            <li class="item"><a href="/item-2.1">Item 2.1</a></li>
            <li class="item"><a href="/item-2.2">Item 2.2</a></li>
        </ul>
    </li>
    <li class="item"><a href="/item-3">Item 3</a></li>
    <li class="item"><a href="/item-4">Item 4</a></li>
</ul>

There a lot of ways to achieve this same result using recursion but it sure is easier to read, scalable and extensible, ain't it?

Using default function parameters in Internet Explorer

Today, I wrote a simple method that fetches images from the database via AJAX and also, I defined an empty object as a default parameter:

function fetchImages(obj={}){
    // some code here...
}

fetchImages();

The default obj parameter would contain extra parameters like id, slug and page, which would be then used to fetch a particular group of images, else, it'll fetch a random set of images.

This method worked fine in Google Chrome and Mozilla Firefox but not in Internet Explorer. I thought of inspecting the code and I was facing weird errors like undefined or Expected: ')' on the IE console.

Luckily, I had compared it to the other methods that didn't have any default parameters, so I did a little research and turns out that according to Mozilla's documentation, default function parameters are proposed by the ES6 syntax and at this point, I realized that Internet Explorer doesn't support ES6 syntax. What a bummer! ๐Ÿ˜’

However, there's a way to prevent this from happening by rewriting the method like this:

function fetchImages(obj){
    // Check if obj is defined, else make it assign it as an empty object.
    var data = obj || {};

    // some code here...
}

And BAM! The method worked flawlessly just as it's intended to do so. ๐Ÿ˜Ž

Addtionally, you may refer to the ECMAScript 6 Compatibility table that you might find it quite helpful to check browser compatiblity for Internet Explorer versions 11 and under.