A big part of that is that I haven’t been doing anything new. I did a ton of Trello-related work in about a one-year period and then was done. But I still use it every day and recently found a gap that I decided to close.
My personal Trello board has three columns. “Not Started,” “In Progress,” and “Done.” Pretty simple.
The “Done” column is the one I decided needed some help.
The “Done” column is important to me. It’d be easy to not have one, simply archiving cards as they were completed. I think it’s easy to get lost in a never-ending “Not Started” list without seeing the things that have been completed. Instead, I have a process that runs nightly to archive cards over two months old, after they’ve had time to pass out of my mind.
I’ve been finding of late, though, that that’s not working for me. I see the “Done” column, I know it’s there and that there’s a lot of stuff in it, but that’s what I’ve boiled it down to. “A lot of stuff” that’s done and easy to ignore.
So I decided to add another automated process. This one runs weekly and sends me a message via Slack, detailing how many cards I’ve completed in the last week.
I’m not doing this for analytics or anything. I don’t have any goals to accomplish a certain number of tasks (they’re not estimated or anything so they’re all different sizes, anyway). I just want to get another reminder in front of my face. This one is a little disruptive, so maybe it’ll stick differently.
For the record, the following is the code for this new process (with a little obfuscation):
A look at DetroitHockey.Net’s 25th Season logo on the site’s 24th birthday.
Today marks the 24th birthday of DetroitHockey.Net, my Detroit Red Wings-centric hockey site and the first site I ever created.
Normally the 24th birthday would be the start of the 25th season but in the world of COVID, timelines aren’t what they once were. Nonetheless, earlier today I unveiled a 25th Season logo at DH.N.
I’d been doodling quite a bit in the lead-up to the site’s 24th birthday. I knew I wanted to differentiate the 25th Season logo from the 20th Season logo by putting the “25” front and center, rather than the site logo, but I had a hard time with anything beyond that.
I was trying to avoid using a bounding shape and was focusing on just using “25” and the site logo when I realized I couldn’t make those work the way I wanted to. I didn’t want to do a shield (the DH.N logo) inside of another shield, so I went with a circle as the bounding shape. I felt like the circle needed to be broken up to help distinguish the anniversary logo from the site’s “promotional” logo, so the ribbon came in and the site logo was lowered to break the bounding circle at the bottom.
The ribbon gave a good place for most of the anniversary-related text. Like it is in the site’s “promotional” logo, “DetroitHockey.Net” arches across the top part of the bounding circle.
The four stars across the bottom part of the logo represent the four Stanley Cup Championships the Red Wings have won since the site was founded in 1996.
My one complaint about this is that it feels like there is empty space before and after the “DetroitHockey.Net” text. It’s necessary to have some space to let the individual elements breathe but that feels like just a little too much and I couldn’t figure out a better way to handle it.
On how I learn, how I code, and not sharing well with others.
I’ve always said that I love the open source community because of the opportunity it provides for riffing off of each other. I’ve also acknowledged that I have the tendency to re-invent the wheel. If those seem at odds with each other, it’s because they kind of are.
How that usually works for me is that I’ll Google to see if someone has solved the problem I’m working on and, if so, I’ll learn what I can from what they did and re-work it to fit my specific situation. Then maybe I’ll write about it and embed my code in the blog post.
I do this because I’ve always wanted ideas, not code, from other people. I don’t want to composer install their stuff, I want to see how they did it and then do it myself. So when it comes time for me to share, I write about it but don’t make my code particularly accessible.
There are two problems here. One is that my way isn’t particularly efficient. I need to be better about using other people’s code and not reinventing the wheel. The other is that I’m not sharing well because my code stays locked up in my own repos.
Not sharing. Mrs. Biondolillo would be disappointed in me.
I realized this as I was trying to consolidate a bunch of my code into a framework package. In doing so, I found that I have a bunch of one-off tools and classes. Things that I don’t use much and didn’t bother to build tests for or anything but that might benefit others a bit. And I never put them out there.
So I’m going to start dumping some of these out to GitHub, starting with the current version of my Trello API helper class. If no one uses them, that’s fine. At least they’ll be out there to find out. And I’ll start being a better citizen of the open source community.
It was originally a part of DetroitHockey.Net, which at that time used Invision Power Board as a forum system. When I spun FHS off into its own site, I migrated user management and messaging to a system built around a Slack team. That served us well for several years but it became apparent that it had flaws, one of which being difficulty scaling up. As such, I made the decision to bring Invision Power Board back in, running it alongside the Slack team.
IPB gave me user management out of the box, so I removed much of my custom-built functionality around that.
I was able to add our Slack team as an OAuth2-based login method for IPB, so existing members could continue logging in with their Slack credentials and all of the other Slack integrations in the site could key off of that information.
To allow users to log in and out using the forum functionality but return to a non-forum page from which they came, two changes to IPB code were required in their login class, /community/applications/core/modules/front/system/login.php.
On lines 59-61, we force their referrer check to accept external URLs.
Then at line 259, we check whether not a referrer was defined and, is so, use it.
To determine whether or not a member is logged in in non-forum areas of FHS, we tap into IPB’s session management and use it to populate our own. It’s a little messy, especially as IPB’s code is not meant to be included into a non-IPB codebase. We end up having to do some cleanup but it looks something like this:
First we pull in the session details.
If we need to, we can get the member ID.
Then we revert as many of the changes IPB made as possible.
That gives us an IPB installation acting as single-sign on for the site.
Other points of integration are driven primarily by the IPB API. On league creation, a forum and calendar are created for the league, with the IDs of each stored in the league config so that messages can automatically be posted there later.
I also added tooling that allows for cross-posting between the forums and Slack. As the expectation is that some leagues will continue to use Slack while most use the forums, the idea is for no messages to get lost between the two. This might lead to over-communication but I would rather see that than the opposite.
Thoughts on my recently-completed refactor of Fantasy Hockey Sim, which started out with a small feature request and spiraled out of control.
I recently completed a year’s worth of upgrades to Fantasy Hockey Sim. They were all important changes and the site is better with them completed, but it was never supposed to be that way. I want to try to make some sense of it here.
It started with a suggestion. “Can we track TOI and ATOI for players in their season stats?” That would be time on ice and average time on ice. And, given that we have the number of minutes each player skates in every game, yeah, that should have been easy enough to add.
So I started to add the two new fields to the stat_player table, where each players season stats are stored. Looking at that, though, I was struck by how wrong that table was. And that’s where the snowball started.
A brief history lesson…
Long before Fantasy Hockey Sim was a thought, I was building tools for managing the drwcentral.net Fantasy Hockey League (now the DetroitHockey.Net Fantasy Hockey League). In 2006, I greatly expanded on those tools and developed a system for not just managing the league in its current state but also displaying historical data, such as career stats and past games played.
To do that, I wrote code and designed a database centered around importing archived historical data. In that context, I always knew that stats belonged to Team X and/or Player Y, as played for a given game type of Season Z.
In 2013, I updated this system to handle multiple leagues, so then the stats belonged to Team A and/or Player B in League C for a given game type of Season D.
The problem was that was exactly how the stat_player table was keyed. From the original 2006 design, it had never been updated to have an auto-incrementing key. Instead it had a multi-dimensional key consisting of player_id, team_id, league_id, game_type, and season_id. Additionally, it wasn’t even accurate, as farm league stats were simply another set of fields on the end of the player_stats table.
This might have made sense in the context of the format from which the stats were imported in 2006 but it was wrong for how things were used in 2019.
So I started to fix it.
Leagues have seasons. Seasons have schedules. Schedules are made up of games and have a game type. Leagues have franchises. Each season, a franchise fields a team. A farm team has a parent team. Now stats_player has a player_id, a team_id, and a schedule_id. From that, you can find what league the stat record is for, what franchise it’s for, and whether or not it’s from the farm league.
But then I didn’t stop there.
Games had a home team and an away team, with scores for each. They also had a set of power play stats for each team. But that could be combined into a game_stat_team table, with one team having a flag denoting them as the home team. Goalie stats and skater stats for each game had their own tables but they were merged to become game_stat_player, with position_id denoting whether they’re a goalie or not.
This continued until I had a database structure that I was happy with.
Now I just had to update all of my code to match the new database layout.
That would be no small thing regardless of the state of the codebase coming into this project. I’d just redefined or added the concepts of seasons, schedules, franchises, and teams. I had to build new tooling around that.
On top of that, like the database structure, the site code was based around importing historical data. Much of the code was historical itself, having been originally written in 2006, with new features bolted on as necessary since then. As such, the database redesign led to a major code refactor project.
All started by a request for two new stats fields, for data the system already had available.
So what have I learned from this?
I think it shows that I’d gotten complacent. Both the database and the code connecting to it should have been refactored ages ago but, because they worked just fine, I didn’t touch them. FHS is a personal project, so I can justify this by saying that I didn’t have the time available to go back and do it right, but I think that would just be an excuse.
That said, this project shouldn’t have snowballed in the way that it did. I should have broken it down into smaller chunks. I never would have allowed this in a project at the office, but because it was for one of my own sites, I let it get out of control.
Finally, in an effort to force myself to get the project done, I rolled in several unrelated features and launched them, so that I wouldn’t have the option of continuing on with normal operations of FHS using the old codebase and schema.
By not breaking it down into smaller pieces, I ended up burning out a bit on the project. It took so long to get done and involved so much downtime that I was desperate to work on anything else.
Now that it’s done, I’m relieved to have the site back up and running and that off my plate. I’m also glad to have the opportunity to look back, see what I did wrong, and work to do better next time around.
The number of times I have “quit” the Grand Rapids Griffins’ annual jersey design contest is comical at this point. Last year I even publicly announced that I was done. Then they went and made this year’s edition 90s-themed and I was drawn right back in.
Two years ago the Griffins requested an 80s-themed “fauxback” jersey as part of their contest. I loved it because it raised the question of what makes an 80s-themed jersey.
As I wrote at the time, there were many jersey design elements that became more prevalent in the 1980s, but it was really color that defined the decade. The Griffins were dictating the colors for their contest, though, so I was really curious what they would deem “80s enough” to win. In the end, and perhaps unsurprisingly, I strongly disagreed with their choice, which left me feeling like the question of what makes an 80s jersey was unanswered.
This year, with the challenge being to create a 90s-themed jersey, I believe there are much stronger trends to work with.
While the 1980s saw only two NHL teams relocate and only one go through a major rebranding, the 1990s saw seven expansion teams, three relocations resulting in new team identities, and a whole slew of redesigns. Many of them used the same design elements and most of those changes have since been reverted, resulting in a set of looks that are uniquely 90s.
As such, when the Griffins announced the theme of this year’s contest, for me it wasn’t so much a matter of figuring out what they were asking for as it was figuring out how to make all of those design options work together. An idea popped into my head almost fully-formed. As such, despite my “retirement,” I was drawn back in.
As an aside… I am writing this on August 2 for publish after the design contest is over. I usually spend the entire design period tweaking, then write up my design thoughts and publish them along with my submission right at the deadline. This year, as part of an attempt to put less effort in, I’m submitting my design on the second day of the contest and writing this up for publish after voting is over.
There are six distinctly 90s elements to this jersey. I’ll note who used them in the NHL to show just how prevalent they were (I’m choosing the NHL because their identities are generally more stable and documented than minor leagues).
From their inaugural season to the AHL’s league-wide redesign in 2009, the Griffins’ jerseys featured a shoulder design that was meant to represent the wings of their mascot. I’ve brought them back here. It’s something that’s unique to the team from the era in question.
By using this shoulder pattern, I was unable to take advantage of another trend of the 1990s: alternate logo shoulder patches. They just don’t work on that background.
Diagonal Sleeve Stripes
Diagonal sleeve stripes were used in the NHL prior to the 1990s (specifically, by the Pittsburgh Penguins, Hartford Whalers, and Vancouver Canucks) but in the 90s there were nine teams that introduced them or brought them back, bucking the trend of standard straight stripes. The aforementioned Penguins, Whalers, and Canucks all used them. The expansion Mighty Ducks of Anaheim and Florida Panthers and the relocated Phoenix Coyotes did as well. Redesigns or third jerseys for the Calgary Flames, New York Rangers, St. Louis Blues, and Washington Capitals all featured diagonal sleeve stripes.
Angled Hem Stripes
Most – but not all – teams who introduced diagonal sleeve stripes also paired them with a nonstandard angled set of stripes at the hem. Anaheim, St. Louis, and Washington all went with an asymmetrical version of this element while Calgary and Pittsburgh chose to make a “V” shape of their stripes. Additionally, the Colorado Avalanche featured a mountain-like design along their hem.
I really dislike the asymmetrical look – even if it’s iconic – and the gap in Pittsburgh’s design, so my concept uses something similar to what Calgary’s 1998 third jersey had.
The vertically-arched nameplate was introduced to the NHL by the Detroit Red Wings in 1982. In 1990 it was copied by the Rangers. The Avalanche used it when they relocated in 1995 and the Panthers switched to it in 1998.
While this is hardly a widespread design element from the 90s, the fact that it quadrupled in use over the decade and that the Griffins are the farm team of the originators makes me comfortable including it in the design.
In 1967, the Penguins made their debut wearing rounded numbers, dropping them after a single season. The Rangers broke from tradition in 1976, switching to a completely different jersey that included rounded numbers, which only lasted until 1978. The Red Wings switched to “fancy” numbers for the 1982-83 campaign before immediately switching back. For the first 75 years of the NHL, those were the only times a team didn’t wear some form of block number on their jerseys.
Then the Tampa Bay Lightning came along. After spending their inaugural campaign in a standard – though drop-shadowed – block font, in 1993 they italicized their numbers. That same year, the NHL’s All-Star Game featured jerseys with rounded numbers rather than block. One season later, the Flames had italicized numbers while the Lightning had moved on to a custom “paintbrush”-like font. One more season later, seven teams had at least one jersey that didn’t use a block font.
By the summer of 1999, 14 teams were using a non-block font on at least one of their sweaters.
The Griffins debuted with a custom number (and name) font and I was highly tempted to go back to it. In the end I chose to stick with a slightly-more-generic rounded font, similar to those used by Calgary, Nashville, Phoenix, the Carolina Hurricanes, and the San Jose Sharks.
Tampa Bay’s “paintbrush” numbers might be more memorable than any of them but I just didn’t think they fit the design. My goal (whether it’s the request of the Griffins or not) is to make the most-90s jersey that still looks good, not just cram as much 90s stuff into a jersey as possible.
Angry Mascot Logo
The last element of the jersey is the Angry Mascot Logo. San Jose debuted represented by a Shark biting a hockey stick in half. Florida’s first logo featured a Panther pouncing forward. The New York Islanders rebranded to focus on a fisherman holding a hockey stick, staring angrily.
In the minor leagues the trend of “fierce” logos was even more visible. Between the AHL and the IHL, no fewer than 13 teams introduced branding – of various qualities or rendering – featuring some combination of a snarling animal or fearsome creature between 1990 and 1999, including the Albany River Rats (1993), Carolina Monarchs (1995), Chicago Wolves (1994), Cincinnati Cyclones (1992 and 1993), Denver Grizzlies (1994), Hamilton Bulldogs (1996), Hartford Wolf-Pack (1997), Indianapolis Ice (1996), Kentucky Thoroughblades (1996), Lowell Lock Monsters (1998), Beast of New Haven (1996), Saint John Flames (1998), and Syracuse Crunch (1994).
I have to admit, I don’t like this trend. The Griffins’ original logo does not meet my criteria for “fierce” and I find it to be a better logo than either their current mark or the one I’ve created here. But to stick with the trend, I’ve swapped majesty for musculature. That said, I do feel like, in doing so, it’s moved out of 90s and become a little more modern.
I submitted this jersey in red because I think it looks best. That said, another perceived trend of the 1990s was “black for black’s sake,” seeing teams add black as a team color and introducing black jerseys simply because it was a color that sold well at the time. With that in mind, I created a full jersey set that includes a black alternate.
The funny thing (though I suppose how funny it is depends on how far this design goes in the contest) is that I’m not sure I actually even like this design. It’s easily my least favorite submission to the Griffins’ contest over the years. Given what they’re asking for, though, I think it nails it.
I called “black for black’s sake” a perceived trend because it simply didn’t happen in the NHL the way that it’s portrayed at times. There are other elements that I ignored because, while everyone “knows” 90s design was all about them, it turns out the facts don’t match up with that.
The Calgary Flames added black as a trim color in 1995 with a black alternate jersey in 1998. The Washington Capitals included black as a trim color in their 1995 redesign and added a black alternate in 1997. The Philadelphia Flyers already had black trim and their 1997 alternate was black. That’s three of 28 teams.
Teal? That was just the San Jose Sharks, with the short-lived New York Islanders “fisherman” jerseys using it as an accent.
Similarly, there’s Tampa Bay’s “paintbrush” crazy numbers. Yeah, the Lightning used them for six seasons. And the Mighty Ducks of Anaheim had a one-season alternate with a crazy number font. But that’s it. It didn’t take the league by storm. It was really just one team and a quickly-abandoned alternate for another.
Finally, there’s asymmetrical striping. I called it “iconic” above but it was just Anaheim and St. Louis who used it. Two teams. More teams used symmetrical angled stripes, but those don’t stick in our collective memories. The Islanders’ fisherman jerseys were technically asymmetrical but not in the way we typically think of.
We’ll see how many of these perceived trends end up being applied to designs in the contest.
As I detailed at DH.N itself, the Detroit Tigers forced me to change the site’s logo, claiming that DetroitHockey.Net’s Old English D conflicted with their trademarked Old English D. I don’t agree with this assessment but I also can’t fight it.
Thankfully, I had a little bit of a hint that the Tigers would do this, so I’d begun brainstorming ideas for a new logo, just in case. With the Old English D expected to be unavailable to me, I started thinking about other symbols of Detroit.
I ruled out the Spirit of Detroit statue because I think it’s somewhat awkward to work with, plus Detroit City FC uses it in their badge and trading conflict with one team for another seemed like a bad idea.
From there, I started thinking about Detroit’s flag. I’m a big fan of quartered flags – like those of Detroit, Maryland, Panama, and the Dominican Republic – and thought that I could follow the Baltimore Ravens’ example and use elements from the quartered flag in a shield.
With Detroit placing the city’s seal at the center of their flag, I thought that might be a good place to work in a set of crossed sticks, carrying that forward from my previous designs. I simplified the elements of the flag, reducing 13 stars, three lions, and five fleurs-de-lis down to one each.
The idea didn’t work as well as I had hoped. None of the elements looked quite at place there. The sticks didn’t fill the center circle well and said circle pushed the elements of each quarter into an awkward position.
I thought more about the quarters of Detroit’s flag and what they represented. France, England, and the United States (with the latter taking up two of the four quarters), the three countries that have laid claim to Detroit. The flag is basically about how they came together. DetroitHockey.Net takes those things and adds a fourth: hockey. So I decided to remove the center circle and break the shield up into five sections. I also changed the colors so that the red from Detroit’s flag became “DetroitHockey.Net Red,” the yellow became more of a gold, and the blue darkened to match the red.
This was closer to what I was trying to do, but still didn’t seem right to me, so I worked on tweaking how the shield was broken up. Along the way I changed the size of the shield and the angle and number of the stripes. I settled on seven stripes as it represented the seven Stanley Cup Championships won by the Red Wings at the time that the site that would become DetroitHockey.Net was founded in 1996.
The final changes were to switch to a slightly lighter shade of blue, then emphasize that blue.
For a site representing the Red Wings, the extra blue didn’t seem to be a fit, so I rolled back to my previous attempt and went with that.
Given the importance of the number nine in Red Wings history, I feel it’s highly appropriate that my final design was the ninth iteration.
With so much gold in the new logo, I felt it was appropriate to bring that color into an updated version of the roundel mark I use for the site.
Finally, I sketched out a version of the logo that combines the shield and the roundel by taking the elements from the shield and placing them inside the inner circle of the roundel.
I may never use that design but I’m keeping it around for now.
With the change, the new DetroitHockey.Net logo timeline is as follows:
The circumstances of the change have really clouded my own judgement on this one, but early reaction is positive.
As much as I loved the old logo and spent time building a brand around it, there was a lot of empty space and the black border tended to merge with the red a bit. When designing merchandise, I found myself defaulting to monochrome versions of the logo to resolve that issue.
The new logo is more complicated and requires a little more explanation than I’d like but I really like how the combination of red, gold, and blue turned out. I still have concerns about the red and gold evoking too much of a Detroit City FC feel but, to a certain extent, that’s like saying the old colors were too similar to the Chicago Blackhawks. I’m not too worried about it.
In 2016, I didn’t like that the crest on my submission and the shoulder logo both used the same griffin silhouette. I thought it looked good but was just a little lazy. Also, I had intended to enter a red jersey in the contest and was convinced to switch to black at the last minute, so I wanted to return to that idea.
Additionally, at the end of the 2014 contest there was a lesson that I had learned and promptly forgot: Minor league sports teams like logos that have their team name included. I wanted to take that into consideration this time around.
Keeping all of that in mind, I created a new crest for the red version of my 2016 entry.
I changed the shape of the shield just to change things up a little. Across it is a banner reading “Griffins” in a vaguely old-German font that I think matches the heraldic crest. Above that is a stalking griffin in silhouette – because the griffin in the shoulder logo is standing on two legs, I wanted this one to be down on all fours (though only three are really seen).
Like the griffin in the shoulder logo, this new griffin features a pair of homages to other logos. The tail is the tail that was used in the Griffins’ original logo while the wing is based on the Winged Wheel logo of the Red Wings.
I put the new logo on the red jersey design from 2016 and I thought I was good.
But then I kept thinking.
In 2016, the jersey I actually liked best was the white one, which I wasn’t allowed to submit because the Griffins specifically asked for a dark jersey. This year, not only did they not make that requirement, but their promotional calendar has dates for fan-designed jerseys to be worn both before and after New Years’; which is when the American Hockey League switches from wearing white jerseys at home to dark ones.
I decided to switch to the white jersey. Which immediately gave me trouble with the crest again.
I designed the new crest to work best on red. It’s primarily black with a heavy white outline. That outline disappears on a white jersey, so what to do?
I tried out several different color swaps. Added outlines. Took the opportunity to play with the sleeve numbers a little, then immediately abandon that idea.
In the end, I decided to go with a logo that mixed elements from my previous submissions with some of my new ideas.
The extra outline on the shield helps set it off on the white jersey while not outlining the “banner” keeps the logo from getting too heavy.
And those are combined with the previously-created shoulder logo, which sits opposite the logo of the Griffins’ parent club, the Detroit Red Wings.
One final note is that I use a template that doesn’t allow for a laced collar to be displayed. I would expect one to be used, as shown here.
Aside from the Grand Rapids Griffins, I don’t normally enter jersey design contests. In general, I don’t like “fan designed” jersey contests because rarely does an actual fan of the team win.
I made an exception this year, though, for the Kalamazoo Wings. I can’t rightfully call myself a Kalamazoo fan given their rivalry with the Toledo Walleye, who are affiliated with the Grand Rapids Griffins and Detroit Red Wings, who I actually am a fan of.
The K-Wings do hold a special place in nostalgia for me, though. They were the visitors in the first hockey game I ever went to, a Thanksgiving game against the Muskegon Lumberjacks when both teams were in the old International Hockey League and I was about five years old.
So I decided to give the Wings’ contest a shot and, in all honesty, it didn’t go in the direction I expected it to at all.
My initial thought, since all existing K-Wings marks were off-limits, was to turn to mythology. “Hermes had a winged helmet, didn’t he?” In addition to winged sandals, yes he did. So I set about trying to do something like that.
In my head, I was thinking something kind of like the old Ottawa Senators logo, with the team name in a partial roundel broken by the wings of the helmet. It turns out that “Kalamazoo Wings” is a really hard name to work with without getting letters upside down at some point on the circle.
Also, in all of the logos I’ve worked on in the past, I’ve never tried to draw a face. As I continued working, I got closer to what I wanted. I abandoned Hermes and his traveller’s cap and went for a more Nordic full helmet, but the contest deadline came up quickly and I had a conference and a short vacation planned. It just wasn’t going to come together.
In parallel with the helmet-based logo, I was putting together an alternate logo based around a K in a shield with wings. I liked the general shape right from the start but tried a variety of fonts for the K, colors, etc. That process actually went well, and partway through I realized that I had a couple different options I could run with.
As I ran out of time, I decided that I needed to switch gears. I had a solid logo in my intended alternate and I had a tertiary that could become a secondary in a pinch (which I was in). I had a jersey design already in place from a previous Griffins contest so I pulled the plug on continued sketching and called it done.
The crest, as previously mentioned, is a K inside a shield with wings. In gold and blue, I think it has a bit of an art deco vibe.
That shield is repeated without the wings on the shoulder logo, where it’s adorned with a pair of crossed hockey sticks and the letters KWHC – Kalamazoo Wings Hockey Club.
The jersey itself features a red body and blue sleeves. I wanted to do contrasting-color sleeves as they give the jersey the “winged” look of the Detroit Red Wings’ away jersey, something I think is appropriate for another team named the Wings.
It’s not what I was aiming for but I think it looks good. It’s probably not different enough from the K-Wings current design to win the contest, which is why I’m disappointed that I ran out of time to work on the winged helmet idea, which I think was pretty unique.
I’ve been toying around with Slackbots a bit lately. Back in January I wrote about publishing a Git log to Slack via one. They’re dirt simple to implement and can be really useful.
They can also be fun. I’ve added a couple bots in our office Slack just for posting randomness, running as cron jobs. I figured I’d take a look at them here.
A couple weeks ago one of my coworkers posted a link to the documentation for a seemingly-random PHP function in our dev Slack channel. It wasn’t random, it just pertained to an offline conversation, but we still made some cracks about how he was doing it to spread awareness of the function.
At nearly the same time, he and I both said, “That sounds like a great idea for a Slackbot.” So I made it, and it looks like this:
As you can see, it’s a little more advanced than just posting a link to a PHP.net URL. If PHP.net had metadata on its pages that allowed for a nice-looking Slack unfurl, I might have just done that. Instead I decided to pull content from the page we’re linking to and make the Slack post a little prettier with it.
So how does that all work?
Simple thing here. Get the defined PHP functions and then start a do…while loop. By using get_defined_functions() I’m limiting what our PHPBot can link to but I figured there are enough functions available there that it doesn’t really matter.
We jump into our do…while loop, where we grab a random function from our array of functions and build what should be a PHP.net documentation URL from the name. For some reason, not every function has documentation (or at least not that matches this template), which is why we’re in a do…while loop.
We get the headers for that URL and if no shorturl is defined there, we know we don’t have a valid function documentation page. In that case, we sleep (I like to sleep in situations like this) and unset the URL, then we’ll take another run at the do…while loop.
If we do have a shorturl, we get into the heavy lifting.
We initialize a couple arrays that we’ll use for building our Slack message, then we pull in the HTML from the documentation page and strip out line breaks and any spaces that might start a line. We do that stripping so that the text we use in our message later on looks better.
Then we load that HTML into a DOMDocument and fire up XPath for it so we can target the elements we want a little easier.
We grab the element of the page that contains all of the information about the function by targeting the refentry class.
Inside that element is a div with class refnamediv, which contains an H1 with the function name, a paragraph classed as verinfo with information about what versions of PHP support the function, and a paragraph defining the function classed as refpurpose. We grab each of these as we’ll use them in our message.
If – for some reason – we didn’t get a function name, we sleep (like I said, I like to sleep in these situations) and then head back to the start of our do…while loop.
Having advanced this far, we target the “Description” section of the function documentation page, which has a class of refsect1 description.
Inside that div is an H3 that serves as the section title, a div that contains an example use of the function, a paragraph with a description, and an optional blockquote with notes about the function. We target each of these and pull that content in, then we use them to build the test of our message.
It should be noted that we use markup to make sure that the example is displayed as a code block while the note(s) (if present) are displayed as a quote, mimicking their appearance on PHP.net.
With all of the information we need acquired, we build our message.
The description section title and our formatted text from it are added as a Slack attachment field. That attachment gets the function name as a title (linked to the documentation URL) and it’s text is the version and purpose text we grabbed early on.
We post this all as user “PHPBot” with a hosted avatar. These two steps aren’t necessary as you can define your incoming webhook’s name and avatar, but we’re reusing a webhook for multiple purposes and, as such, define these for each.
Then we hit the end of our do…while loop. We’ve assembled our message so we can move on.
Lastly, we actually send that message. It’s just a cURL post to the Slack webhook URL (obscured here) and ends up posting a message that looks like this:
As I said, there’s nothing too complex here. If anything, this is probably over-complicated. But it gives us something to talk about at 2:05 every day.
Last week another coworker posted to our developer channel asking that we all send a random photo of a Yak to one of our non-dev coworkers. My immediate thought was that this was begging to be made into a Slackbot, and thus the YakBot was created.
We bring in the Google search API for this one in addition to the Slack API but overall it’s a bit simpler because there’s less of a message to build.
The first thing we do is define our Google search API key and the ID of the custom search engine that we’re using. Then we build an array of possible recipients of our yak. The recipients include our developer channel as well as individual user IDs, to whom the message would be sent in the form of a direct message from Slackbot.
Next we select a random number between 1 and 91. This is because the Google search API won’t let you request a start point higher than 91 for some reason. The search results return ten items, which means the most results you can get is 100. We only need one and one 1/91 is close enough to 1/100 so I do the randomizing up front and then do the lookup and take the first response.
Here we actually do that lookup. We get JSON back and decode it to pull out the first item listed.
Once we have our image URL, we build our message, which is relatively simple compared to the PHPBot message because all we’re doing is posting an attachment with an image. As I mentioned above, we also define a custom username and avatar, though we don’t need to.
Finally, we wrap it up by determining who to send our yak to. We loop through each of our channels and generate a random number between zero and nine. If the number is zero, we add that channel to the list of recipients.
We do that because it allows for some randomness. It’d get noisy if we were posting yaks too often or too regularly.
Then we loop through the list of recipients and send the message, defining the channel along the way. The lucky winners end up getting something like this: