Month: July 2019

Home / Month: July 2019

A minimal WordPress Theme

July 20, 2019 | Coding | No Comments

WordPress Logo

The company I work for is growing, and part of that growth has me learning WordPress. Id honestly rather not touch it, I do not enjoy working in PHP. But there it is anyway.

I was quickly surprised at how simple, and how little you need to make a theme. You only need two files: index.php and style.css. So I decided to make one that was that simple to demonstrate here.

Shortly into it I decided to add a menu and a sidebar, so two more files: functions.php and sidebar.php. How functional is a theme really, if you don’t have a customizable menu or widget area?

All the code is below, comments inline and github repo is available.

style.css

/*
Theme Name: Minimal WordPress
Theme URI: https://wordpress.org/themes/twentyseventeen/
Author: the WordPress team
Author URI: https://wordpress.org/
Description: Minimal WordPress brings your site to life with immersive featured images and subtle animations. With a focus on business sites, it features multiple sections on the front page as well as widgets, navigation and social menus, a logo, and more. Personalize its asymmetrical grid with a custom color scheme and showcase your multimedia content with post formats. Our default theme for 2017 works great in many languages, for any abilities, and on any device.
Version: 1.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: minimaltheme
Tags: one-column, two-columns, right-sidebar, flexible-header, accessibility-ready, custom-colors, custom-header, custom-menu, custom-logo, editor-style, featured-images, footer-widgets, post-formats, rtl-language-support, sticky-post, theme-options, threaded-comments, translation-ready
This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what you've learned with others.
*/

index.php

<?php
/*
Everything is going to be displayed on this one page,
we don't want to put potentially thousands of posts on 
our one page... so we redefine the query to paginate.
But only if we are not on a single item page.
*/

if (!is_singular()) {
    $paged = (get_query_var('paged')) ? get_query_var('paged') : '1';
    $args = array(
        'nopaging'               => false,
        'paged'                  => $paged,
        'posts_per_page'         => '2',
        'post_type'              => 'post',
    );
    $query = new WP_Query($args);
} else {
    $query = $wp_query;
}


?>

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>My Theme</title>
    <!-- wp_head will inject all of wordpress's specific header info
    and anything else we define, like custome css.  We could just write that
    in here ourselves, but we could end up with mulitple headers and this
    helps keep us DRY
    -->
    <?php wp_head() ?>
</head>

<body>
    <nav>
        <div class="nav-wrapper  container">
            <a href="/" class="brand-logo"><?php echo get_bloginfo('name'); ?></a>
            <?php
            wp_nav_menu(array(
                'theme_location' => 'main-menu',
                'container_class' => 'right'
            ));
            ?>
        </div>
    </nav>
    <main class="container">
        <div class="row">
            <div class="col s12 m8">
                <?php if ($query->have_posts()) : while ($query->have_posts()) : $query->the_post(); ?>
                        <article class="card-panel">
                            <h3>
                                <a href="<?php the_permalink(); ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a>
                            </h3>

                            <small><?php the_time('F jS, Y'); ?> by <?php the_author(); ?></small>

                            <div class="entry">
                                <!-- we only want to show the full post if we aren't on a list -->
                                <?php if (is_singular()) {
                                    the_content();
                                    // If comments are open or we have at least one comment, 
                                    // load up the comment template.
                                    if (comments_open() || get_comments_number()) {
                                        comments_template();
                                    }
                                } else {
                                    the_excerpt();
                                } ?>
                            </div>
                            <p class="postmetadata"><?php _e('Posted in'); ?> <?php the_category(', '); ?></p>

                        </article>

                    <?php endwhile;
                    // show pagination links
                    echo paginate_links(array(
                        'total' => $query->max_num_pages,
                        'mid_size' => 2
                    ));

                else : ?>
                    <p><?php esc_html_e('Sorry, no posts matched your criteria.'); ?></p>
                <?php endif; ?>
            </div>
            <div class="col s12 m4">
                <?php get_sidebar() ?>
            </div>
        </div>
    </main>


    <footer>
        <!-- like wp_head wp_footer injects necessary script stuff
            such as the code that gives us the WordPress Admin bar
         -->
        <?php wp_footer(); ?>
    </footer>
</body>

</html>

functions.php

<?php
/* 
You can register your stylesheets and scripts in the same function
but I prefer to keep them seperate, it just feels cleaner to me
*/
function minimaltheme_enqueue_styles()
{
    wp_enqueue_style('materialize-css', "https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css");
}
add_action('wp_enqueue_scripts', 'minimaltheme_enqueue_styles');

function minimaltheme_enqueue_scripts()
{
    wp_enqueue_script('materialize-js', "https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js");
}
add_action('wp_enqueue_scripts', 'minimaltheme_enqueue_scripts');
wp_enqueue_style('style', get_stylesheet_uri());


/*
  We need one menu for our nav bar, but you can register
  as many as you like and put them anywhere
*/
function register_menus()
{
    register_nav_menu('main-menu', __('Main Menu'));
}
add_action('init', 'register_menus');


// register a sidebar to user throughout the site
add_action('widgets_init', 'minimaltheme_register_sidebars');
function minimaltheme_register_sidebars()
{
    register_sidebar(array(
        'name' => __('Main Sidebar', 'minimaltheme'),
        'id' => 'sidebar',
        'description' => __('Widgets in this area will be shown on all posts and pages.', 'minimaltheme'),
        'before_widget' => '<div class="card"><div class="card-content">',
        'after_widget'  => '</div></div>',
        'before_title'  => '<div class="card-title">',
        'after_title'   => '</div>',
    ));
}

sidebar.php

<?php
if (!is_active_sidebar('sidebar')) {
    return;
}

dynamic_sidebar('sidebar');

Available at https://github.com/wsimmerson/minimaltheme

Shell

I stumbled onto this Reddit post today. A rant, but one I agree with hardheartedly.

I recently changed jobs. The person following me to my last job will come in to thorough documentation, step by step instructions, etc. The job I just started hasn’t a shred. Word is the guy before me (only at the job 6 months, so there is some excuse) didn’t document, and the guy before him (12 years) destroyed all his documentation on the way out the door.
I don’t know a sysadmin who doesn’t keep some kind of notes. At minimum, throw them in a shared doc or notebook or something. At this new place I get the brunt of the two types of non-documenters: the lazy and the malicious.
Isn’t documenting as you go and leaving the documentation behind for the next poor sap just part of the ethical code of the job, or am I wrong?

r/sysadmin • Posted byu/rabadashridiculous

What really got to me is his citation that a sysadmin, who had been in the job for twelve years destroyed all his notes on the way out. It doesn’t surprise me however that there are no formal documentation policies.

That sysadmin, who destroyed his notes effectively destroyed the companies property, yes that work product was owned by his former employer. They could take action against him.

No matter how he felt, this is not professional or acceptable behavior.

However, every place I have worked, when i arrived was in the same boat. No formal documentation policies, if I was lucky a few print outs or a collection of saved emails.

If you encounter this situation in a new job, do yourself a favor and take it upon yourself to set a new standard. Fire up a small web server on the local network, load a CMS like WordPress or Drupal, give you fellow admins access, and start documenting.

You will make life easier for everyone in the office, including and especially, yourself.

barbell deadlift

When I first started working out it was for health and to loose the belly fat. Something that I was successful at through running, and later through BodyBeast and Intermittent Fasting. Since changing to Strong Lifts/Starting Strength however, I have gained more weight than I ever have before.

A lot of that is muscle, I am incompatibly stronger now than when I started but a lot of it is also fat. So it’s time to do something to cut that fat again, but Ill get to that a bit later.

My barbell and plate set totals 300lbs, which I believe should be enough for anyone for general fitness. If you want to train for power lifting you will need more, but that’s not my purpose. So when I started I set my strength goals as:

GoalCurrent
Squat 5×5300lbs300lbs
Dead lift 1×5300lbs295lbs
Bench Press 5×5225lbs200lbs
Row 5×5no goal215lbs
Seated Over Head Press 5×5no goal130lbs
  • Seated over head press because my ceiling is low and the weights hit it, otherwise I would be standing.

Its been about 10 months now and I am getting so very close to hitting my goals on my primary lifts. But I feel like it’s time to make some changes. First, I’m sure I can hit my Dead lift goal. But with the structure of the program by the time I get to the dead lifts I am already exhausted from the squats and ohp, and I am finding squatting 3 times a week at that weight to be too much to properly recover from.

With that in mind I’m changing up the program. My “B” workout will no longer include squats, and I only want to dead lift once per week and do those first. This means my Wednesday workout will look like: Dead lift, OHP, Need to add an additional exercise here.

I’m confident that this change will not only allow me to hit my dead lift goal, but the benching twice per week (Monday and Friday) will help me hit that goal as well. Once those are hit, the plan is to shift to a hypertrophy style program (yet to be determined). I may just stay with the program, deload and raise the rep ranges + some other accessory lifts.

Now, as for the cutting of the fat. The last time I managed to get my body fat ratio down it was by intermittent fasting 20/4 5 days a week. I could easily do that again, but I worry that the lack of calories would be really detrimental to my progress over all, so I’m going to only do it on my non-lift days. Specifically Tuesday, Thursday and maybe Saturday. I find the weekend the hardest time to stick to this, its much easier to NOT eat when at work.

As of this morning, I weight 203lbs. My ideal weight is around 170, though at 5’9″ I could go lower, but I think that would be pushing it.

Thats it for now, wish me luck. Have any comments, questions or advice please comment below!

Update:

I’ve decided to change things up a bit more. I mentioned above that I was going to change things up to a more hypertrophy based workout once I had hit my strength goals, but I think I can do both at the same time.

I’m going to keep the basic format of the program, but instead of 5×5 I’m going to borrow from Martin Berkhans Leangains program and adopt Reverse Pyramid Training.

The way this works is after your warm up, you do a set at your heaviest weight for AMRAP(As Many Reps As Possible) with a goal of 8 reps (6 for dead lifts). You then take 10%(5% for Bench & OHP) off and again do another set AMRAP, then take 10% off that and do another set AMRAP. If you hit your 8 rep goal then you raise the max weight on that lift 5lbs the next time.

This, according to its proponents, allows you to both hit strength and hypertrophy ranges while also speeding up the workout, so you can get out of the gym faster.

Wish me luck!

PipEnv

July 10, 2019 | Coding | No Comments

python programming language

Here I am, apparently late to the party again. Set in my ways, using the same old — trustworthy — tools and along comes another one, seemingly better.

Pipenv will eventually be included in pip itself, but for now we have to pip install it. Hopefully you’re using Python 3, because that’s where you need to get it, although once you have it you can use it to create Python 2 environments.

Pipenv gets rid of the necessity for a requirements.txt file — but can both use and generate them — instead using two files a Pipfile and Pipfile.lock. The pipfile to me, is very reminiscent of a npm package.json while the Pipfile.lock “locks” the specific package versions, dependencies and hashs.

Instead of creating the virtual env specifically pipenv creates one in your home directory based on the current folder name. You can get around this by creating a .venv directory in your current folder, which pipenv will prioritize.

C:\code\myproject>pipenv shell
Creating a virtualenv for this project…
Pipfile: C:\code\myproject\Pipfile                                                                                      Using c:\users\wayne\appdata\local\programs\python\python37-32\python.exe (3.7.0) to create virtualenv…
[ ===] Creating virtual environment...Already using interpreter 
....
Installing setuptools, pip, wheel...
done.

Successfully created virtual environment!                                                                               Virtualenv location: C:\Users\Wayne\.virtualenvs\myproject--MmAU6cW
Creating a Pipfile for this project…                                                                                    Launching subshell in virtual environment…

You will see that a .virtualenvs with the current folder name was created in my home directory. But if I create a .venv directory and run pipenv shell again…

C:\code\myproject>pipenv shell
Creating a virtualenv for this project…
Pipfile: C:\code\myproject\Pipfile                                                                                      Using c:\users\wayne\appdata\local\programs\python\python37-32\python.exe (3.7.0) to create virtualenv…
[ ===] Creating virtual environment...Already using interpreter 
...
Installing setuptools, pip, wheel...
done.

Successfully created virtual environment!                                                                               Virtualenv location: C:\Users\Wayne\.virtualenvs\myproject--MmAU6cW
Creating a Pipfile for this project…                                                                                    Launching subshell in virtual environment…

Now we have a new one in the .venv

We can also specify a specific python version by pipenv –python=version.number

We now have a Pipfile in our project directory that looks like:

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]

[requires]
python_version = "3.7"

Notice the seperation of dev-packages and packages. We can now deploy our projects and not include test runners that found their way into requirements.txt in production. Lets install something.

$ pipenv install flask

Pipenv has been updated to:

[packages]
flask = “*”

We also now have a Pipfile.lock file that looks like:

{
    "_meta": {
        "hash": {
            "sha256": "a82b674d67d29678775ff6b773de1686a9593749ec14483b0d8e05131b662286"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.7"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "click": {
            "hashes": [
                "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
                "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
            ],
            "version": "==7.0"
        },
        "flask": {
            "hashes": [
                "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52",
                "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6"
            ],
            "index": "pypi",
            "version": "==1.1.1"
        },
        "itsdangerous": {
            "hashes": [
                "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
                "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
            ],
            "version": "==1.1.0"
        },
        "jinja2": {
            "hashes": [
                "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
                "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
            ],
            "version": "==2.10.1"
        },
        "markupsafe": {
            "hashes": [
                "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
                "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
                "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
                "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
                "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
                "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
                "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
                "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
                "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
                "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
                "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
                "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
                "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
                "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
                "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
                "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
                "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
                "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
                "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
                "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
                "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
                "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
                "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
                "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
                "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
                "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
                "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
                "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
            ],
            "version": "==1.1.1"
        },
        "werkzeug": {
            "hashes": [
                "sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c",
                "sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6"
            ],
            "version": "==0.15.4"
        }
    },
    "develop": {}
}

This file includes the specific version of flask and all of its dependencies. This file will be updated every time we install, upgrade or remove a package.

This would be a incredibly long post if I continued to post demonstrations for everything this can do, so below is a descriptive cheat sheet that should be self explanatory.

Cheat Sheet

Activate the shell
pipenv shell

Initialize environment with a specific python version
pipenv –python=2.7.3

Install from Pipfiles
pipenv install

Install in production
pipenv install –deploy

Install a development dependancy
pipenv install nose –dev

Install all packages specified in Pipfile.lock
pipenv sync

Install from a requirements.txt file
pipenv install -r ./requirements.txt

Check for known security issues in your installed packages
pipenv check

View a graph of all your dependencies
pipenv graph

Update the Lock file before deploying
pipenv lock

Ignore the pip file
pipenv install –ignore-pipfile

Installs all packages specified in Pipfile.lock
pipenv –rm

Show the path to the virtual env
pipenv –venv

Create a requirements.txt file (if your team refuses to change to pipenv)
pipenv run pip freeze > requirements.txt

Deactivate the shell
exit

Getting Stronger!

July 10, 2019 | Health & Fitness | No Comments

barbell deadlift

I’ve been through a lot of different fitness and exercise programs over the years. Military PT, half-marathons, DVD programs like TiBo, P90X, BodyBeast, etc. The latter, BodyBeast I did for two years… 6 days a week.

It worked well for me, I built muscle lost body fat, got stronger. However, after watching the same videos 6 days a week for two years, I got bored and reached a point where those dumbbells just weren’t doing it for me any more. I had maxed out my weights, so progress was stalled.

At that point I started looking for something else, something that would allow me to keep progressing. I found StrongLifts 5×5 which is based on Starting Strength, a program focused on the “main” heavy compound lifts. I invested in a 300lb barbell and plate set, and a squat rack.

I’m very glad I did.

The program is broken into two workouts A and B, and is run three days a week alternating between the two as such.

MondayWednesdayFriday
Week 1ABA
Week 2BAB
Week 3ABA
Workout AWorkout B
Squat 5×5Squat 5×5
Bench 5×5Press 5×5
Row 5×5Deadlift 1×5

The reason this is effective is because of the consistent, progressive overload. Starting the program, I began with the empty barbell which is 45lbs. Every workout you put another 5 lbs on the bar, when it eventually gets too heavy you keep the same weight for a couple workouts. If you still cant get through them, take 10% off and work your way back up.

I’ve been at this now for 9 months and I can squat 300lbs. Something that was mind blowingly heavy just months ago. My body weight has gone up, but my waist size has gone down. Chest is bigger, arms are bigger, legs..

I feel and look way better than I did. The only thing really holding me back now is diet and beer. I go through phases where I cut back the beer and lock down my diet, but it never lasts long. Have to get more disciplined.

If you’re looking for a effective fitness program that is only 3 days a week and simple to follow, this is the one.

PyCharm Save Actions

July 9, 2019 | Coding | No Comments

programming code

I think I’m late to the party on this, but wanted to throw out my gleeful support of this plugin. Automatically cleanup and/or format your code when you save a file, or run against several files.

This should be part of PyCharm itself and not just a plugin, its that useful. https://plugins.jetbrains.com/plugin/7642-save-actions

If you use PyCharm on a daily basis like me, just do yourself the favor and install it.

TwitterBot!

July 9, 2019 | Coding | No Comments

twitter

I’ve been a bit bored, haven’t been able to come up with a new personal side project for a while. Last night I realized I hadn’t done any browser automation stuff, and what better way of learning it than building a Twitter bot?

Caveat: This is probably a violation of Twitters terms of service so use for educational purposes only!

So what I’ve done is taken Python and with Selenium automated the process of signing into Twitter, searching a specific hashtag, get a list of tweets and like them. All this interspersed with some short, random weight times to mimic more human like behavior.

The repo can be found at https://github.com/wsimmerson/twitterbot but it is only two files, the bot itself and a config file with variables such as username and password, excluded from git of course.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import random
import time
import sys

import config


class TwitterBot():
    def __init__(self, username, password):
        self.username = username
        self.password = password

        try:
            self.hashtag = config.HASHTAG
        except:
            print("config.HASHTAG must be defined")
            sys.exit(1)

        try:
            self.pages_to_scroll = config.PAGES
        except:
            self.pages_to_scroll = 10

        self.bot = webdriver.Chrome()

    def activate(self):
        print("running...")
        self.bot.get("https://twitter.com/login")
        time.sleep(3)

        usernameBox = self.bot.find_element_by_class_name("js-username-field")
        usernameBox.clear()
        usernameBox.send_keys(self.username)

        passwordBox = self.bot.find_element_by_class_name(
            "js-password-field")
        passwordBox.clear()
        passwordBox.send_keys(self.password)
        passwordBox.submit()

        time.sleep(15)
        self.bot.get(
            "https://twitter.com/search?f=tweets&vertical=default&q=%23{}&src=tyah".format(self.hashtag))

        for x in range(1, self.pages_to_scroll):
            self.bot.execute_script(
                "window.scrollTo(0, document.body.scrollHeight);")
            # for more humanesque scrolling behavior
            time.sleep(random.randrange(10, 30))

        links = []
        for tweet in self.bot.find_elements_by_class_name("tweet"):
            links.append(tweet.get_attribute("data-permalink-path"))

        for link in links:
            self.bot.get("https://twitter.com/{}".format(link))
            favBtn = self.bot.find_element_by_class_name("js-actionFavorite")
            try:
                favBtn.click()
            except Exception as e:
                # sometimes the clicks fail, not sure why yet.
                print("Error: ", e)
            # How long does it take for a human to read a tweet?
            time.sleep(random.randrange(20, 60))


if __name__ == '__main__':
    bot = TwitterBot(config.USERNAME, config.PASSWORD)
    bot.activate()

The config.py file requires:
USERNAME=
PASSWORD=
HASHTAG= (don’t actually add the #, its in the search string by default)
and an optional
PAGES= (this defaults to 10 if not present; determines how many tweets you will find on the page)

It took me about an hour or so to get this working and I may extend it out further. I.E. retweet, if the number of likes is over a specific threshold or exclude tweets that contain certain words, etc. Otherwise, this was a very short project and my quest to find something better continues.

Convert strings to HEX Colors

July 4, 2019 | Coding | No Comments

programming code

I’ve been working with charts.js and data being generated from the python backed of the API. Since the data is changing all the time, and the nature of the different queries, I never know how many data sets will be generated to plot.

This makes it difficult to define a specific set of colors to go with the unknown quantity of labels. At first I wrote a function to generate a random color code, but then, on every page reload, everything is a different color.

This of course, makes the experience rough and kinda annoying the longer you’re on the page, pulling different queries. A different approach was in order.

The individual data sets have unique names, which get used for labels. So I thought, why not try to use those names to create hex color codes? Well it turns out its really simple to do.

def convertToHexColor(word):
    word = "AB" + word.upper()
    buff = ""
    for c in word:
        buff += "{}".format(ord(c))
    word = "000000" + hex(int(buff)).lstrip("0x")

    return "#" + word[-6:]

That’s it. It’s small, but I created a github repo for it. If you need it, enjoy.
https://github.com/wsimmerson/convertToHexColor