A couple people asked how to see their stats after I talked about it on the Dabs post yesterday. Here's the script, updated to be usable by people who aren't Python nerds.

And if you're not a programmer, maybe wait until some other folks have looked over the code to make sure it's not doing anything funky. I've tested this and didn't put anything malicious in there, but it's still good practice.

For comparison, National Novel Writing Month entails writing 50,000 words at an average rate of 1,667/day.

"""
This script displays a wordcount for all your comments & posts on Hexbear

If you don't know how to run a Python script, you can paste the entire thing
into an online compiler since running unvetted scripts from internet
strangers is a bad idea.

STEP 1) Go here: https://www.programiz.com/python-programming/online-compiler/
STEP 2) Copy-paste this entire script into the box
STEP 3) Replace "liberal" with your username. Do not remove quotation marks
STEP 4) Click the Run button
"""


USERNAME = "liberal"


# If you're not a programmer, just ignore the rest of the file


import json
from datetime import datetime
from string import punctuation
from urllib.request import Request, urlopen as fetch
from urllib.parse import urlparse, urlencode, urlunparse
from urllib.error import HTTPError


# Some people will include the u/ or /u/ prefix
if USERNAME.startswith('/'):
    USERNAME = USERNAME[1:]
if USERNAME.startswith('u/'):
    USERNAME = USERNAME[2:]


def word_list(s: str) -> list:
    """Naively split a string into words. May have weird edge cases with Markdown and doesn't ignore quotes"""
    mapping = str.maketrans('', '', punctuation)
    no_punctuation = s.translate(mapping)
    return no_punctuation.split()


def fetch_json(url: str):
    """Fetch/parse json response at url"""
    request = Request(url, headers={
        'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
        'Content-Type': 'application/json'
    })
    try:
        response = fetch(request)
    except HTTPError as error:
        message = error.fp.read()
        data = (
          json.loads(message) if message.startswith(b'{')
          else {'error': str(message, encoding='utf-8')} if len(message) > 0
          else {'error': 'unknown error'}
        )
        return {'success': False, 'data': data}
    else:
        data = json.load(response)
        return {'success': True, 'data': data}


def build_url(*, username: str):
    """Build API url for fetching user details"""

    base_url = 'https://hexbear.net/'
    path = 'api/v1/user'
    query = {
        'username': username,
        'sort': 'New',
        'limit': 30000,
        'saved_only': 'false'  # Why on earth would Python not encode False with a lowercase f by default?
    }
    return urlunparse(urlparse(base_url)._replace(
        path=path,
        query=urlencode(query)
    ))


def main():
    url = build_url(username=USERNAME)
    response = fetch_json(url)
    success, data = response['success'], response['data']
    if not success:
        return print('An error occured: {}'.format(data['error']))
    
    comments = [c['content'] for c in data['comments']]
    posts = [f"{p['name']} {p['body']}" for p in data['posts']]
    activities = comments + posts
    words = [word for activity in activities for word in word_list(activity)]

    total_count = len(words)
    unique_count = len(set(words))
    account_created = data['user']['published'][:10]
    account_created = datetime.strptime(account_created, '%Y-%m-%d').date()
    days_lapsed = (datetime.now().date() - account_created).days
    print(f'/u/{USERNAME} has written {total_count:,} ({unique_count:,} unique) words since {account_created}.')
    print(f"That's an average of {total_count // days_lapsed:,} per day.")


if __name__ == '__main__':
    main()
  • eXAt [he/him]
    ·
    3 years ago

    /u/eXAt has written 7,557 words since 2020-07-26. That's an average of 12 per day.

    You will never make me post more.

  • Kanna [she/her]
    ·
    edit-2
    3 years ago

    /u/kanna has written 83,894 words since 2021-03-16.
    That's an average of 239 per day.

    • KermitTheFraud [they/them]
      hexagon
      ·
      3 years ago

      There's an API call that will literally return all of your comments and posts in their entirety. So it fetches those, splits them up into words, and then counts. It's probably a little off because the way I'm splitting up words is a little naive, but it should be mostly accurate

    • KermitTheFraud [they/them]
      hexagon
      ·
      3 years ago

      https://github.com/formcept/whiteboard/tree/master/nbviewer/notebooks/data/harrypotter

  • Alex_Jones [he/him]
    ·
    3 years ago

    /u/alex_jones has written 75,122 (10,882 unique) words since 2021-08-23. That's an average of 391 per day.

    I like knowing this. Very cool information, comrade! :rat-salute:

      • marxisthayaca [he/him,they/them]
        ·
        3 years ago

        I post a lot of book club announcements and those are a lot of stuff to write. Technically I can't claim all the credit for a lot of that.

        • KermitTheFraud [they/them]
          hexagon
          ·
          3 years ago

          That’s fair. I was originally going to try to exclude quoted text but I don’t think it would have been worth the time honestly

  • KollontaiWasRight [she/her,they/them]
    ·
    3 years ago

    /u/KollontaiWasRight has written 27,140 words since 2021-08-01. That's an average of 127 per day.

    Less than I might have expected, but I guess I've mostly been snarky of late.

  • Tomboys_are_Cute [he/him, comrade/them]
    ·
    3 years ago

    /u/Tomboys_are_Cute has written 30,622 words since 2020-07-29. That's an average of 52 per day.

    I've got rookie numbers. I need to write a megthread or three

  • GreenTeaRedFlag [any]
    ·
    3 years ago

    /u/GreenTeaRedFlag has written 118,343 words since 2021-03-10. That's an average of 331 per day.

    I'm writing half a short paper a day, that's pretty good.

  • hexaflexagonbear [he/him]
    ·
    edit-2
    3 years ago

    if USERNAME.startswith('/'):

    USERNAME = USERNAME[:1]

    if USERNAME.startswith('u/'):

    USERNAME = USERNAME[:2]

    Maybe I'm misunderstanding this, but isn't the colon on the wrong side here?

  • Femboiboiboi [any]
    ·
    3 years ago

    Teach me to be a nerd I don't want to be poor anymore ty.

    • KermitTheFraud [they/them]
      hexagon
      ·
      3 years ago

      Honestly, I wish I worked as a programmer. No one will hire me without a degree and I know people with degrees who have applied for fucking hundreds of positions and only gotten a couple interviews. I make almost $20/hour, which is okay for the cost of living where I'm at. I'm not a regular at the soup kitchen anymore. But fuck I am so underutilized at work

      • invalidusernamelol [he/him]
        ·
        edit-2
        3 years ago

        Yo, read the ArcGIS documentation and apply for GIS jobs saying you know Python scripting. You'll start at like $25+ and be doing way simpler stuff than this.

        Another option is reading the Autolisp docs and applying for drafting automation jobs. Seems like people who can do good scripting work are rare in the drafting field because they all get better jobs lol

        • KermitTheFraud [they/them]
          hexagon
          ·
          3 years ago

          No shit? Obviously I took a while sprucing it up, but this script initially took me like 10 minutes to write. I didn't think it got much simpler than calling an API and counting words.

          • invalidusernamelol [he/him]
            ·
            3 years ago

            Yep, that's what GIS scripting is like. I've been doing a lot of using Arc's geometry objects to find drawing errors and doing spacial data assignments (also just api calls or objects for local databases).

            Same with Autolisp lol. I started at $17 doing telecom drafting and am now at $25 after 7 months because I was the only one able to do basic scripting lol

  • KurtVonnegut [comrade/them]
    ·
    3 years ago

    Thanks for the script, this is fun.

    /u/KurtVonnegut has written 11,119 (3,485 unique) words since 2021-03-12. That's an average of 31 per day.

  • Alex_Jones [he/him]
    ·
    3 years ago

    Also for the past six years, I thought Nanowrimo was 100k words and I always felt like shit for falling short.

  • SeventyTwoTrillion [he/him]
    ·
    edit-2
    3 years ago

    3496 words since 2020-07-24, 5 per day. But I've only been on this account for 58 days so that's 60 per day 58,700 words since 2022-01-03, an average of 1012 per day. I'm more terminally online than I thought

    • KermitTheFraud [they/them]
      hexagon
      ·
      edit-2
      3 years ago

      You need to replace USERNAME = "liberal" with USERNAME = "SeventyTwoTrillion"

      Edit: is this a joke about you being a liberal? lol