FroshKiller All American 51911 Posts user info edit post |
Back in 2009, I started working on a Greasemonkey script for the Wolf Web. A year later, I made a for-real release, worked on it for a few more months, and wound up not spending much time on the Wolf Web.
I've picked the project back up and have basically started a total rewrite. It occurred to me that there were probably people in Tech Talk who might be interested in the process: making decisions about what features to implement and how to implement them, tuning slower functions, etc.
First, let me tell you about my original idea.
The Scaffold The Wolf Web's HTML has more or less always been a mess from a semantic standpoint. Every single page is a collection of nested tables populated by anonymous elements.
I could see that on any given page, there was a lot of useful information about the content. The problem was that it was difficult to get at any of it. If I was going to add any new features at all, I'd have to tame that jungle.
What I had to do first was set a bunch of IDs and classes on the elements I was interested in using. This would make it much easier to traverse the DOM and get what I wanted. I call this skeleton the scaffold. By adding a little markup to certain pages, I made it much easier to work on new features.
My goal for the scaffold is to make this process fast and invisible to the end user. If a power user decides he wants to add his own feature to the script, he'll be able to use the scaffold. This means I'm going to have to rewrite the script to put all the scaffolding in one module, and I'll probably need to document it on an external site.
jQuery The very first thing I wrote for the script was an XPath query to see whether the user was logged in and to capture the username. XPath is a goddamn nightmare for Web pages, though.
I decided to use jQuery for DOM traversal and manipulation instead. Greasemonkey allows you to require external resources, so I just plugged that in. I hadn't worked with jQuery much prior to that—I was more of a Prototype guy—but I figured I might as well learn something new while I was learning something else new.
That was a slam dunk. Prototype is nice, but jQuery is much better suited to extending other people's work in my opinion and seems to be more actively supported.
Initial Feature Set No one cares about the scaffold thing. They only care about what can be done with it.
The most requested feature, like, ever is user blocking. I don't like it, but I decided right away to include it as a powerful example of what was possible. A good example like that was important to me because I wanted to convey that the script itself was a base the end user could build on. That hasn't really happened, but I'll talk about that later.
The rest of the stuff was just good housekeeping: converting IFRAMEs to links, changing YouTube links to embedded videos, adding photo gallery links beneath posters' info, etc. These were just easy things to develop that provided an immediate benefit.
External Services Greasemonkey scripts can make cross-site requests, which meant I could use jQuery's AJAX functions with external services. Initially, I just had the script hit a PHP script on some Web space of mine to send me an e-mail whenever one user blocked another.
Then, I got the idea to allow users to flag NSFW threads. I created two simple scripts (one to vote, one to check thread statuses) and a simple database back end that the Greasemonkey script could take advantage of.
That's been far and away the most fun and (in my opinion) useful aspect of the script. After I picked it back up, I decided that I would extend this feature even further to implement some community policing and content rating stuff I had proposed as new features for the Wolf Web itself.
The Rewrite Without getting into fine details in this first post, I'm really overhauling the script. Below are my goals. I'll be documenting my progress in this thread.
- User preferences - Greasemonkey lets you store some individual settings per userscript, but it doesn't have any sort of front-end method to change settings. I'll create a preferences page that can be called up from the script menu or keyboard shortcut so users can more easily change their options.
- Voting and karma - I have a database. Might as well use it. I want to keep track of users' opinions of each other.
- Classifieds - I don't really care for Classifieds as a message board. I'd rather be able to group threads (FS/WTB/etc.) and maybe flag taken items as sold so I don't have to click.
- Drafts - I had to save the draft for this post in my Drafts folder in Gmail. Wouldn't it be nice if I could just file away drafts when posting a topic or reply and call them up later?
- Custom highlight styles - I like NSFW threads with a red background, and I like seeing my own threads with a tooltip yellow background. But not everyone shares my preferences. Why not let people define their own colors and words to watch for?
Anyway, I'll be posting about implementing this stuff and soliciting feedback. Once I've got the new scaffolding done, I'll set up a "dev channel" sort of link so anyone who's interested can install what I'm actually working on and see how it's going.1/25/2012 6:23:41 PM |
Prospero All American 11662 Posts user info edit post |
Whatever happened to Site3 and will this script be enabled for it?
<-no premie 1/25/2012 6:37:41 PM |
FroshKiller All American 51911 Posts user info edit post |
Good question. I'd asked qntmfred whether I should hold off on working on the script for Site 3. I don't think we're likely to see it soon, so I'm pretending it doesn't exist.
In theory, it'd be relatively easy to convert the script if that layout ever goes live. 1/25/2012 6:41:07 PM |
dave421 All American 1391 Posts user info edit post |
^think he said open beta for site 3 was going to be sometime this month so you should have plenty time to test & get feedback on both before it goes fully live. Thanks for the reminder too. I forgot to install it on this computer. 1/25/2012 11:43:30 PM |
Noen All American 31346 Posts user info edit post |
The really cool thing about you using jQuery is that it's at least possible to integrate your scripts into core functionality of Tdub over time.
Keep it up man! 1/26/2012 1:25:36 AM |
FroshKiller All American 51911 Posts user info edit post |
dave421 said:
Quote : | "^think he said open beta for site 3 was going to be sometime this month so you should have plenty time to test & get feedback on both before it goes fully live." |
You got a link to where he said that? I've been holding off on any Site 3 stuff since August of 2010.
Noen said:
Quote : | "The really cool thing about you using jQuery is that it's at least possible to integrate your scripts into core functionality of Tdub over time.
Keep it up man!" |
Yeah, I noticed T-Dub is using jQuery now. Most of the kind of stuff I'm doing should probably take place server-side. Unfortunately, I don't have that kind of freedom.
Thanks for the encouragement!
Posting a reply reminds me that I wanted to add a quoted reply feature.1/26/2012 8:25:24 AM |
FenderFreek All American 2805 Posts user info edit post |
This + original format >>>> Site 3. I've yet to be impressed by anything about it, but this sounds cool as hell. 1/26/2012 8:45:04 AM |
BIGcementpon Status Name 11318 Posts user info edit post |
^^In PP, 4th post down from the top. message_topic.aspx?topic=604823&page=6 1/26/2012 10:43:57 AM |
catalyst All American 8704 Posts user info edit post |
what will be the lower bound on negative karma
i would like to achieve that value 1/26/2012 10:51:07 AM |
dakota_man All American 26584 Posts user info edit post |
1/26/2012 11:55:43 AM |
FroshKiller All American 51911 Posts user info edit post |
Good question about karma. I want to get good ideas out of this thread. Here are some ideas I posted back in August of 2010:
Quote : | "Users should be able to vote on posts—not other users, not threads, just posts. The "vote" for a user will be the votes for his posts, after all, and the same applies to threads.
You use the votes to determine karma totals for users, threads, message boards, whatever can "own" a post.
If you want to vote just up or down, the karma rating is just a single number, higher is better. If you want other dimensions for voting (e.g. this isn't just bad, it's [old]), karma gets more complex. But let's run with the simple example.
Current flood control applies to users at an even 0 karma. There are simple tiers you fall into depending on how good or bad your karma is relative to the baseline. I wouldn't have more than two in either direction to keep it simple. So you have the best level, a good level, baseline, a bad level, and a really bad level.
Every time you post, it's an opportunity for the community to influence your karma. When you post a thread, every user's vote should carry a little more weight.
Every vote you make carries weight based on your karma. A bad user's vote doesn't count as much as a good user's vote. Sorry, but that's the way it is.
Karma degrades over time, maybe monthly. You have to contribute if you want to keep a good level. I want this to keep motherfuckers from resting on their laurels. Yeah, you might have been the man in 2004, but you don't post like you ought to, you don't vote like you ought to, nobody votes for your ass, so get to steppin'.
In the simple system, karma is a small, whole number. Level -1, 0, 1, etc. Doesn't go higher than 4 or 5 or something. Votes typically aren't whole numbers themselves. That weight your vote carries based on your karma? We might be talking about 0.01 or something.
Maybe have separate scores in each message board. Just 'cause I'm the shit in Entertainment doesn't mean I get to post a thread every 15 minutes in Tech Talk." |
1/26/2012 3:14:24 PM |
dakota_man All American 26584 Posts user info edit post |
Why don't you just go start /r/thewolfweb and get to work on a red and white stylesheet? 1/26/2012 3:15:47 PM |
FroshKiller All American 51911 Posts user info edit post |
I don't do the Reddit thing. 1/26/2012 3:33:27 PM |
afripino All American 11425 Posts user info edit post |
I think the first step should be to purchase tww.com 1/27/2012 3:24:05 AM |
FroshKiller All American 51911 Posts user info edit post |
I've just copied the script to a different host. Time to really start. What do we got on the spacecraft that's good? Let's start with the Greasemonkey metadata:
// ==UserScript== // @name Better Wolf Web // @author Jonathan Hamilton // @namespace http://jlhamilt.freeshell.org/ // @version 1.0 // @description Extensions for the Wolf Web // @include http://*thewolfweb.com/* // @include http://*brentroad.com/* // @require http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js // @require http://lolibrary.org/bww/scaffold.js // @require http://lolibrary.org/bww/gm_jq_xhr.js // ==/UserScript==
All right, familiar name and namespace. Probably need to update that version number. It runs on thewolfweb.com and brentroad.com, but I think I want to exclude Site 3 for now since the layout will be incompatible with the current scaffolding.
What external resources am I using? An old version of jQuery, my scaffold library, and a library that wraps overrides jQuery's AJAX requests to force them to use Greasemonkey's GM_xmlhttpRequest method.
I'm not a fan of change for the sake of change, so I'm going to stick with that version of jQuery for now unless it turns out there's a bug or vital new feature I need. I will move the external resources on the old host to this other one, though, and update the version number and shit:
// ==UserScript== // @name Better Wolf Dev // @author Jonathan Hamilton // @namespace http://jlhamilt.freeshell.org/ // @version 1.0 // @description Extensions for the Wolf Web // @include http://*thewolfweb.com/* // @include http://*brentroad.com/* // @exclude http://site3.thewolfweb.com/* // @require http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js // @require http://jlhamilt.freeshell.org/bwd/scaffold.js // @require http://jlhamilt.freeshell.org/bwd/gm_jq_xhr.js // ==/UserScript==
Boom! Welcome to Better Wolf Dev. Feel free to download it if you want to follow along with development, but be advised that it's probably going to be broken 9 times out of 10.1/27/2012 9:13:01 AM |
FroshKiller All American 51911 Posts user info edit post |
When I look at this script, I see some things I don't like. I've got some function declarations in here which should probably be hidden away, a bunch of user blocking stuff, and a sorry excuse for control flow when it comes time to decide which functions to run based on which kind of page we're viewing.
I want to change this up. My goal for this part of the script is to have some clean control flow and a separate library for the blocking function.
I figure I'll probably want to put each feature in its own module where possible, so I might as well establish a naming convention. I'll start with bww.blocking.js. I create the new file, move the function declarations for the blocking stuff into it, and add the file as a new external resource in my metadata.
I don't bother to comment or even alphabetize the blocking stuff. This is just a quick and dirty test. Reinstalling and blocking Golovko confirms that we're still in business. Cool.
Already, the main body of the script is much more readable. I'll go ahead and comment the blocking functions now that they're mostly in one place. After I'm done with that, I should consider addressing that control flow. 1/27/2012 9:27:46 AM |
qntmfred retired 40726 Posts user info edit post |
why not host it on github? that way you'll get version control, issue tracking and even wiki for documentation 1/27/2012 9:56:54 AM |
FroshKiller All American 51911 Posts user info edit post |
Seems like overkill to me. I didn't think I really needed source control for a tiny project like this.
What say you, Tech Talk? Would you like this bird moved to GitHub? 1/27/2012 10:05:00 AM |
gs7 All American 2354 Posts user info edit post |
Github keeps you from having to worry about host issues ... and it's actually real easy to use. 1/27/2012 10:33:32 AM |
Prospero All American 11662 Posts user info edit post |
GitHubit 1/27/2012 10:44:18 AM |
EuroTitToss All American 4790 Posts user info edit post |
SOCIAL CODING, B 1/27/2012 10:58:01 AM |
kiljadn All American 44690 Posts user info edit post |
github that shit, son 1/27/2012 6:32:38 PM |
dakota_man All American 26584 Posts user info edit post |
++github 1/27/2012 7:10:45 PM |
Noen All American 31346 Posts user info edit post |
to me, github is a great place to put it, to me.
or codeplex 1/27/2012 9:52:37 PM |
FenderFreek All American 2805 Posts user info edit post |
++ 1/28/2012 9:36:02 AM |
spöokyjon ℵ 18617 Posts user info edit post |
If anybody's looking for a simpler solution to fixing TWW, I just whipped something up myself: BOOM. 1/28/2012 9:56:23 AM |
kiljadn All American 44690 Posts user info edit post |
hahahaha 1/28/2012 12:44:05 PM |
Grandmaster All American 10829 Posts user info edit post |
doesn't work with tampermonkey 1/28/2012 6:15:49 PM |
spöokyjon ℵ 18617 Posts user info edit post |
That's crazy b/c I did super expansive testing. 1/28/2012 9:10:41 PM |
FroshKiller All American 51911 Posts user info edit post |
I made a GitHub repository, but I still think it's overkill. Slowed me down like whoa and killed my impulse to update this thread.
https://github.com/FroshKiller/Better-Wolf-Web
I'll stick with it due to popular demand, but I don't understand why anyone would want or need a git repo for, like, four fucking text files. 1/29/2012 6:14:09 PM |
lewisje All American 9196 Posts user info edit post |
I personally have an SVN repo for a huge number of text files: https://code.google.com/p/jansal/wiki/PassiveSecurity 1/29/2012 7:30:27 PM |
FenderFreek All American 2805 Posts user info edit post |
^^ It's just to keep it in one place and to be sure that you're always grabbing the latest version. I find it very convenient for hosting any shared code, no matter how small. I would still rely on this thread for discussion, but but using a repo makes viewing and retrieving the source much simpler. 1/30/2012 1:10:44 PM |
FroshKiller All American 51911 Posts user info edit post |
Yeah, how is that any different than me keeping the latest version in one folder on my host like I was originally doing? 1/30/2012 1:28:36 PM |
dakota_man All American 26584 Posts user info edit post |
Keeping it in a folder won't earn you scene points in the blogosphere. On rails. 1/30/2012 1:59:42 PM |
CaelNCSU All American 7082 Posts user info edit post |
^^
You can see the diff across multiple changes (including local), branch it, and approve changes that others make more effectively...
SVN is like going back to vacuum tubes.
^ Rails is so 2008, all the cool kids are using Node
[Edited on January 30, 2012 at 2:06 PM. Reason : a]
[Edited on January 30, 2012 at 2:07 PM. Reason : a] 1/30/2012 2:03:28 PM |
FroshKiller All American 51911 Posts user info edit post |
But I'm not interested in changes others make. I encourage people to customize their installations, sure, but I ain't trying to incorporate anyone else's work into this. And all that other shit I can do with local source control. I think Dakota's right. :/ 1/30/2012 2:25:01 PM |
gs7 All American 2354 Posts user info edit post |
FroshKiller, for your hard work, you get:
[Edited on January 30, 2012 at 3:08 PM. Reason : .] 1/30/2012 3:04:04 PM |
FroshKiller All American 51911 Posts user info edit post |
Let's talk about how votes work and how I want to make 'em better.
Basically, I have a big stupid table with a record for every thread that someone has reported as NSFW. It's not really that simple, but you get the idea.
In the original script, whenever you visited a page that had a list of threads (e.g. message_section.aspx), the script posted a request to a script on a remote server. This request sent a list of all the thread IDs on the page, and the script returned an array of which threads (if any) had been flagged.
One of my goals for the new version is to support other types of voting. I have a real nice framework for recording arbitrary votes that reflect a thread's content...but how do I determine which type of vote should be reported to the user? Fifty people click [old], twenty click [lol]. Which is it going to be?
Every user gets one vote per post. I already had that control in place. For the time being, I've decided to create a view on the database for the highest vote count for each thread. The script now returns the most popular vote per thread. 2/7/2012 9:50:52 PM |
jackleg All American 170957 Posts user info edit post |
IS THIS A MELWARE 2/7/2012 9:58:26 PM |
FroshKiller All American 51911 Posts user info edit post |
I could capture your Wolf Web password! I could also distribute your Wolf Web password to other clients, intercept all login attempts by script users, and sign them in as a different user randomly. 2/7/2012 10:00:47 PM |
dakota_man All American 26584 Posts user info edit post |
Quote : | "One of my goals for the new version is to support other types of voting." |
This sounds like a mistake. Just have an up/down voting system and a tagging system. If you did it arbitrarily enough people could vote on tags that already existed (or adding a duplicate tag uses the voting system to track the prevalence of that tag.)
This way, you could add one of those shitty word clouds to everything!
Maybe I'm just too used to the way reddit works (which I like,) so if I were going to offer a novel suggestion it would be the following: Implement something like a daily allowance of "extra" votes. If, for example, each user gets 2 of these per day then each day they could vote something they really like up by 3, or vote something they really hate down by 3.2/8/2012 12:04:42 PM |
FroshKiller All American 51911 Posts user info edit post |
Well, don't say it sounds like a mistake when I haven't even given more detail than just "other types of voting"!
In the original script, you could report a post as NSFW, like I said. The script would highlight NSFW posts in red so you knew which ones to avoid.
I'm talking about letting the script handle other types of content classification like that via voting, not some popularity contest shit. Like I mentioned in my first post, Classifieds is kind of dumb as a message board. I can parse FS/WTB threads into separate sections, but not everyone uses that shorthand. If users (trusted users, maybe) could flag threads in Classifieds as FS or WTB, the script could more reliably group the threads correctly. 2/8/2012 12:31:35 PM |
dakota_man All American 26584 Posts user info edit post |
You're right. I should have said that based on your description I imagine a cluttered and confusing barrage of different voting icons on everything. I still think a separate tagging system paired with an arbitrary up/down voting system would suffice -- that way you wouldn't have to rely on trust for flagging (tagging) classified threads, you could just assume that the most popular tag on a FS post will be "FS." 2/8/2012 7:26:25 PM |
FroshKiller All American 51911 Posts user info edit post |
GitHub killed my enthusiasm for rewriting Better Wolf Web, so I said fuck all that bullshit and have started from scratch again. Now, I have new goals.
Minimize Side Effects
Some of my original functions do more than one thing, and it's not clear that they do more than one thing. For example, checkLogin sets a Greasemonkey script value to the currently logged-in username and also returns that username. In the interest of simplifying the script, I'm going to change that. Instead, checkLogin will return the username, and I'll set the script value by calling the function. It's not a big type of change, but it's a disciplined one that will help me keep things straight in the long run.
Add Custom Events
It will be easier for users to customize the script if it fires custom events that users' modifications can respond to. For instance, all scaffolding functions should trigger a "scaffolding finished" sort of trigger. I can bind all additional functionality in Better Wolf Web itself to respond to that as an example of how to extend it.
I may not waste much time on this. It boils down to whether an event fired by one Greasemonkey script can be responded to by another. If that's the case, people could create and publish their own extensions with Better Wolf Web as a dependency.
Undo Premature Optimizations
For some dumb reason, I thought I should filter the users in a thread down to only the unique users. Why? You have any idea how many posts are on a given page of a thread in the worst case? Hint: It's 50. Who the hell cares if you iterate over the same user 50 times?
I also did a lot of post processing (processing of posts) inline during scaffolding. Holy hell, it'd be easier and clearer to select a group of scaffolded elements afterwards and just do the work on them directly. Who cares if it takes another 50 ms? 4/22/2013 10:09:18 PM |
FroshKiller All American 51911 Posts user info edit post |
Just had a fun hour of troubleshooting.
When I first released BWW, jQuery 1.3.2 was the current stable release, so I implemented it. Since I'm rewriting it now, I figured I should upgrade to something newer, namely 1.9.1.
Lo and behold, my cross-site Ajax requests stopped working, which meant the NSFW warning and flagging features stopped working.
As you might know, using jQuery for Ajax in a Greasemonkey script requires a bridge between the Greasemonkey's XmlHttpRequest handler and jQuery in order to make cross-site requests. I suspected there might be an incompatibility between the bridge and the newer jQuery library, but because of the way Greasemonkey is sandboxed, I wasn't seeing any errors or warnings pop up on my error console.
I finally debugged the son of a bitch and found that jQuery expects the XmlHttpRequest handler to implement a function called getAllResponseHeaders. JavaScript doesn't really have any means of declaring class interfaces, and my bridge didn't implement a function with that name, so I had no idea until I debugged. Once I defined that function, hey presto, the feature started working again. 4/23/2013 11:31:24 AM |