Beispiel #1
0
def conjure_handler(nick):
    """
    Generats a mysterious item and gives it to the named person.
    """
    global SELF

    thing = "{adjective} {stuff}".format(adjective=chatter.say("adjective"),
                                         stuff=chatter.say("stuff"))
    count = TOWNIES.get(nick).give_item(thing)

    return "here, take this {thing}! you've got {things} from me now.".format(
        thing=thing, things=p.no("thing", count))
Beispiel #2
0
def graffiti_handler():
    '''
    Main graffiti handler.
    '''

    if os.path.isfile(WALL_LOCK):
        redraw("sorry, "+chatter.say("friend")+", but someone's there right now. try again in a few!\n")
    else:
        subprocess.call(["touch", WALL_LOCK])
        redraw()
        print("""\
the graffiti wall is a world-writeable text file. anyone can
scribble on it; anyone can move or delete things. please be
considerate of your neighbors when writing on it.

no one will be able to visit the wall while you are here, so don't
worry about overwriting someone else's work. anything you do to the
wall will be recorded if you save the file, and you can cancel
your changes by exiting without saving.

""")
        raw_input("press <enter> to visit the wall\n\n")
        subprocess.call([SETTINGS.get("editor"), WALL])
        subprocess.call(["rm", WALL_LOCK])
        redraw("thanks for visiting the graffiti wall!")
Beispiel #3
0
def did(channel, user, msg):
    """
    Responders to ACTIONs.
    """

    response = []
    global SELF

    if user == "kelpiebot":
        ## handler for ,get response
        if msg.startswith("retrieves"):
            if msg.find("hands it to " + BOTNICK) != -1:
                item = " ".join(msg.split("retrieves ")[1:]).split(
                    " and hands it to")[0].split(" ")[1:]
                item[0] = item[0][1:]
                item[-1] = item[-1][:-1]

                thing = " ".join(item)
                inv = SELF.get("inv", [])
                inv.append(thing)
                SELF.update({"inv": inv})
                print("got " + thing)
                save_self()

                response.append("{sweet}! thanks for the {thing}!".format(
                    sweet=chatter.say("positive"), thing=thing))

    return response
Beispiel #4
0
    def disconnect(self):
        '''
        Disconnects from server.
        '''

        self.send("QUIT " +chatter.say("sleep") + "\n")
        self.sock.close()
Beispiel #5
0
def graffiti_handler():
    '''
    Main graffiti handler.
    '''

    if os.path.isfile(WALL_LOCK):
        redraw("sorry, "+chatter.say("friend")+", but someone's there right now. try again in a few!")
    else:
        subprocess.call(["touch", WALL_LOCK])
        redraw()
        print("""\
the graffiti wall is a world-writeable text file. anyone can
scribble on it; anyone can move or delete things. please be
considerate of your neighbors when writing on it.

no one will be able to visit the wall while you are here, so don't
worry about overwriting someone else's work. anything you do to the
wall will be recorded if you save the file, and you can cancel
your changes by exiting without saving.

""")
        raw_input("press <enter> to visit the wall\n\n")
        subprocess.call([SETTINGS.get("editor"), WALL])
        subprocess.call(["rm", WALL_LOCK])
        redraw("thanks for visiting the graffiti wall!")
Beispiel #6
0
def init():
    try:
        raw_input("""
i don't recognize you, stranger. let's make friends.

press <enter> to begin, or <ctrl-c> to get out of here.
        """)
    except KeyboardInterrupt:
        print("\n\nthanks for checking in! i'll always be here.\n\n")
        quit()

    users = open(USERFILE, 'a')
    users.write(USER+"\n")
    users.close()
    subprocess.call(["mkdir", PATH])
    subprocess.call(["mkdir", CONFIG])
    subprocess.call(["mkdir", DATA])

    header = gen_header()
    headerfile = open(os.path.join(CONFIG, "header.txt"), 'w')
    for line in header:
        headerfile.write(line)
    headerfile.close()

    subprocess.call(["cp", os.path.join(SOURCE, "config", "defaults", "footer.txt"), CONFIG])

    setup()
    #subprocess.call(["cp", os.path.join(SOURCE, "config", "defaults", "style.css"), WWW])
    core.load()

    raw_input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n")
    return ""
Beispiel #7
0
def addressed(channel, user, now, msg, network=""):
    """
    Responses when directly addressed. Assumes addressed before being called.
    Does a check for townie record.
    """

    global SELF

    response = []
    responding = True
    townie_check(user)
    if channel != BOTNICK:
        tag = user + ": "
    else:
        tag = ""

    if msg.find("botsnack") != -1:
        time.sleep(2)
        response.append(botsnack_handler(user))
    elif msg.find("time") != -1:
        response.append(tag + str(now))
    elif msg.find("<3") != -1:
        time.sleep(1)
        response.append(tag + ":)")
    elif msg.find("sync") != -1:
        response.append(tag + str(SELF.get("mark", 0)))
    elif msg.find("mark") != -1:
        SELF.update({"mark": now})
        save_self()
        response.append(tag + "sync! ({time})".format(time=now))
    elif msg.find(":(") != -1:
        time.sleep(2)
        response.append(tag + chatter.say("cheer"))
    elif msg.find(":)") != -1:
        time.sleep(2)
        response.append(tag + ":D")
    elif msg.find("report") != -1:
        response.append("!tildescore")
    else:
        if user == "tildebot":
            response.append({"channel": ADMIN, "msg": msg})
        else:
            time.sleep(3)
            response.append(tag + chatter.say("no answer"))

    return response
Beispiel #8
0
def stop():
    '''
    closer

    * prints ending text
    '''

    return "\n\n\t"+chatter.say("bye")+"\n\n"
Beispiel #9
0
def stop():
    '''
    closer

    * prints ending text
    '''

    return "\n\n\t"+chatter.say("bye")+"\n\n"
Beispiel #10
0
    def part(self, chan):
        '''
        Leaves named channel, and removes it from the global channel list.
        '''

        print(self.CHANNELS)
        self.CHANNELS.remove(chan)
        self.send("PART "+ chan +" :"+chatter.say("sleep")+"\n")
Beispiel #11
0
def main_menu():
    menuOptions = [
            "record your feels",
            "review your feels",
            "check out your neighbors",
            "browse global feels",
            "change your settings",
            "send some feedback",
            "see credits"]
    print("you're at ttbp home. remember, you can always press <ctrl-c> to come back here.\n\n")
    #print("you're at ttbp home.\n\n")
    print_menu(menuOptions)

    try:
        choice = raw_input("\ntell me about your feels (or 'quit' to exit): ")
    except KeyboardInterrupt:
        redraw(EJECT)
        return main_menu()

    if choice == '0':
        redraw()
        today = time.strftime("%Y%m%d")
        write_entry(os.path.join(DATA, today+".txt"))
        www_neighbors(find_ttbps())
    elif choice == '1':
        redraw("here are your recorded feels, listed by date:\n\n")
        view_own()
    elif choice == '2':
        users = find_ttbps()
        redraw("the following "+p.no("user", len(users))+" "+p.plural("is", len(users))+" recording feels on ttbp:\n\n")
        view_neighbors(users)
    elif choice == '3':
        redraw("now viewing most recent entries\n\n")
        view_feed()
    elif choice == '4':
        pretty_settings = "\n\ttext editor:\t" +SETTINGS.get("editor")
        pretty_settings += "\n\tpublish dir:\t" +os.path.join(PUBLIC, SETTINGS.get("publish dir"))
        pretty_settings += "\n\tpubishing:\t"+str(SETTINGS.get("publishing"))

        redraw("now changing your settings. press <ctrl-c> if you didn't mean to do this.\n\ncurrent settings "+pretty_settings+"\n")
        try:
            setup()
        except KeyboardInterrupt():
            redraw(EJECT)
        raw_input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n")
        redraw()
    elif choice == '5':
        redraw()
        feedback_menu()
    elif choice == '6':
        redraw()
        show_credits()
    elif choice in QUITS:
        return stop()
    else:
        redraw(INVALID)

    return main_menu()
Beispiel #12
0
    def admin_panel(self, channel, user, time, msg):
        '''
        Various admin-only commands.
        '''

        if msg.find("!join") == 0:
            self.say(channel, "k", user)
            split = msg.split(" ")
            for x in split:
                if x.find("#") != -1:
                    self.joinchan(x)
                    return "join"

        elif msg.find("!brb") == 0:
            self.say(channel, chatter.say("sleep"), user)
            self.part(channel)
            return "part"

        elif msg.find("!quit") == 0:
            self.say(channel, chatter.say("sleep"), user)
            self.disconnect()
            return "die"

        elif msg.find("!names") == 0:
            self.send("NAMES "+channel+"\n")
            return "names"

        elif msg.find("!channels") == 0:
            chanlist = " ".join(self.CHANNELS)
            self.say(channel, "i'm in "+chanlist)
            return "names"

        elif msg.find("!wall") == 0:
            split = msg.split("!wall ")
            wallmsg = "".join(split[1])
            self.wall(wallmsg)
            return "wall"

        elif msg.find("!say") == 0:
            splitter = msg.split("!say ")[1]
            parse = splitter.split(" ")
            self.say(parse[0], " ".join(parse[1:]))
            return "say"
        else:
            self.multisay(channel, cndorphbot.admin_panel(channel, user, time, msg))
Beispiel #13
0
def seen(channel, user):
    """
    Handler for processing join actions.
    """

    time.sleep(random.randrange(2, 4))

    response = []
    msg = ""

    if user == BOTNICK:
        print("joined " + channel)
        msg = "{greet}, {townies}!".format(greet=chatter.say("greet"),
                                           townies=p.plural(
                                               chatter.say("friend")))
    else:
        townie_check(user)

    if msg:
        response.append(msg)
    return response
Beispiel #14
0
def init():
    '''
    new user creation

    * introduces user
    * calls setup functinos
    '''

    try:
        raw_input("""
i don't recognize you, stranger. let's make friends.

press <enter> to begin, or <ctrl-c> to get out of here.
        """)
    except KeyboardInterrupt:
        print("\n\nthanks for checking in! i'll always be here.\n\n")
        quit()

    ## record user in source list
    users = open(USERFILE, 'a')
    users.write(USER + "\n")
    users.close()

    ## make .ttbp directory structure
    subprocess.call(["mkdir", PATH])
    subprocess.call(["mkdir", CONFIG])
    subprocess.call(["mkdir", DATA])

    ## create header file
    header = gen_header()
    headerfile = open(os.path.join(CONFIG, "header.txt"), 'w')
    for line in header:
        headerfile.write(line)
    headerfile.close()

    ## copy footer and default stylesheet
    subprocess.call([
        "cp",
        os.path.join(SOURCE, "config", "defaults", "footer.txt"), CONFIG
    ])
    subprocess.call([
        "cp",
        os.path.join(SOURCE, "config", "defaults", "style.css"), CONFIG
    ])

    ## run user-interactive setup and load core engine
    setup()
    core.load(SETTINGS)

    raw_input("\nyou're all good to go, " + chatter.say("friend") +
              "! hit <enter> to continue.\n\n")
    return ""
Beispiel #15
0
    def to_string(self, oneline=True):
        """
        String representation of this townie.
        """

        if len(self.aliases) < 2:
            aliases = "no other known aliases"
        else:
            aliases = ", ".join(self.aliases)

        if oneline:
            return """a {townie} named {nick}, who also goes by {aliases}""".format(
                townie=chatter.say("friend"),
                nick=self.nick,
                aliases=aliases,
            )
        else:
            return """\
    a {townie} named {nick} who has given me {botsnacks}""".format(
                townie=chatter.say("friend"),
                nick=self.nick,
                botsnacks=p.no("botsnack", self.snacksGiven))
Beispiel #16
0
def trick():
    """
    Pull a random command and return it. If no commands learned, just smile
    vacantly.
    """
    trick = random.choice(SELF.get("tricks", [":)"]))
    if trick in ["!water", "!talklike"]:
        ## manual targetted tricks
        trick = "{trick} {target}".format(trick=trick,
                                          target=random.choice(TOWNIES.keys()))
    if trick in ["!wiki-philosophy"]:
        trick = "{trick} {target}".format(trick=trick,
                                          target=chatter.say("stuff"))

    return trick
Beispiel #17
0
def botsnack_handler(nick):
    """
    Increments own botsnack received count, and botsnack given count for
    {nick}; returns an affectionate phrase.
    """
    global SELF

    TOWNIES.get(nick).give_botsnack()
    count = SELF.get("botsnacks", 0)
    count += 1
    SELF.update({"botsnacks": count})
    save_self()

    return "{nick}: {affection}".format(nick=nick,
                                        affection=chatter.say("affection"))
Beispiel #18
0
def main_menu():
    #os.system("clear")
    #print(BANNER)
    #redraw()
    menuOptions = [
            "record feelings",
            "check out neighbors",
            "change settings",
            "send feedback",
            "(wip) see credits"]
    #print(SPACER)
    print("you're at ttbp home. remember, you can always press <ctrl-c> to come back here.\n\n")
    print_menu(menuOptions)
    #print("how are you feeling today? ")

    try:
        choice = raw_input("\ntell me about your feels (enter 'none' to quit): ")
    except KeyboardInterrupt:
        redraw("eject button fired! going home now.")
        return main_menu()

    if choice == '0':
        redraw()
        today = time.strftime("%Y%m%d")
        write_entry(os.path.join(DATA, today+".txt"))
    elif choice == '1':
        redraw("the following users are publishing on ttbp:\n\n")
        view_neighbors()
    elif choice == '2':
        pretty_settings = "\n\ttext editor:\t" +SETTINGS["editor"]
        pretty_settings += "\n\tpublish dir:\t" +os.path.join(PUBLIC, SETTINGS["publish dir"])

        redraw("now changing your settings. press <ctrl-c> if you didn't mean to do this.\n\ncurrent settings "+pretty_settings+"\n")
        setup()
        raw_input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n")
        redraw()
    elif choice == '3':
        redraw()
        feedback_menu()
    elif choice == '4':
        redraw(DUST)
    elif choice == "none":
        return stop()
    else:
        redraw(INVALID)

    return main_menu()
Beispiel #19
0
def check_init():
  global SETTINGS
  print("\n\n")
  if os.path.exists(os.path.join(os.path.expanduser("~"),".ttbp")):
      print(chatter.say("greet")+", "+USER+".")
      while not os.path.isfile(TTBPRC):
        setup_handler()
      try:
        SETTINGS = json.load(open(TTBPRC))
      except ValueError:
        setup_handler()

      raw_input("\n\npress <enter> to explore your feels.\n\n")
      core.load()
      return ""
  else:
    return init()
Beispiel #20
0
def setup():
    '''
    master setup function

    * editor selection
    * publishing toggle
    * publish/unpublish as needed
    * directory selection

    TODO: break this out better?
    '''

    global SETTINGS

    print("\n\ttext editor:\t" + SETTINGS.get("editor"))
    if core.publishing():
        print("\tpublish dir:\t" +
              os.path.join(PUBLIC, str(SETTINGS.get("publish dir"))))
    print("\tpubishing:\t" + str(SETTINGS.get("publishing")) + "\n")

    # editor selection
    SETTINGS.update({"editor": select_editor()})
    redraw("text editor set to: " + SETTINGS["editor"])

    # publishing selection
    SETTINGS.update({"publishing": select_publishing()})
    core.reload_ttbprc(SETTINGS)
    update_publishing()
    redraw("blog publishing: " + str(core.publishing()))

    if core.publishing():
        print("publish directory: ~" + USER + "/public_html/" +
              SETTINGS.get("publish dir"))

    # save settings
    ttbprc = open(TTBPRC, "w")
    ttbprc.write(
        json.dumps(SETTINGS, sort_keys=True, indent=2, separators=(',', ':')))
    ttbprc.close()

    raw_input("\nyou're all good to go, " + chatter.say("friend") +
              "! hit <enter> to continue.\n\n")
    redraw()

    return SETTINGS
Beispiel #21
0
def init():
    '''
    new user creation

    * introduces user
    * calls setup functinos
    '''

    try:
        raw_input("""
i don't recognize you, stranger. let's make friends.

press <enter> to begin, or <ctrl-c> to get out of here.
        """)
    except KeyboardInterrupt:
        print("\n\nthanks for checking in! i'll always be here.\n\n")
        quit()

    ## record user in source list
    users = open(USERFILE, 'a')
    users.write(USER+"\n")
    users.close()

    ## make .ttbp directory structure
    subprocess.call(["mkdir", PATH])
    subprocess.call(["mkdir", CONFIG])
    subprocess.call(["mkdir", DATA])

    ## create header file
    header = gen_header()
    headerfile = open(os.path.join(CONFIG, "header.txt"), 'w')
    for line in header:
        headerfile.write(line)
    headerfile.close()

    ## copy footer and default stylesheet
    subprocess.call(["cp", os.path.join(SOURCE, "config", "defaults", "footer.txt"), CONFIG])
    subprocess.call(["cp", os.path.join(SOURCE, "config", "defaults", "style.css"), CONFIG])

    ## run user-interactive setup and load core engine
    setup()
    core.load(SETTINGS)

    raw_input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n")
    return ""
Beispiel #22
0
def check_init():
    '''
    user handler

    * checks for presence of ttbprc
    * checks for last run version
    '''

    global SETTINGS

    print("\n\n")
    if os.path.exists(os.path.join(os.path.expanduser("~"),".ttbp")):
        print(chatter.say("greet")+", "+USER+".\n")

        '''
        ## ttbprc validation
        while not os.path.isfile(TTBPRC):
            setup_repair()
        try:
            SETTINGS = json.load(open(TTBPRC))
        except ValueError:
            setup_repair()
        '''

        ## ttbp env validation
        if not valid_setup():
            setup_repair()

        ## version checker
        mismatch = build_mismatch()
        if mismatch is not False:
            switch_build(mismatch)
        if not updated():
            update_version()

        ## when ready, enter main program and load core engine
        raw_input("press <enter> to explore your feels.\n\n")
        core.load(SETTINGS)

        return ""
    else:
        return init()
Beispiel #23
0
def setup():
    '''
    master setup function

    * editor selection
    * publishing toggle
    * publish/unpublish as needed
    * directory selection

    TODO: break this out better?
    '''

    global SETTINGS

    print("\n\ttext editor:\t" +SETTINGS.get("editor"))
    if core.publishing():
        print("\tpublish dir:\t" +os.path.join(PUBLIC, str(SETTINGS.get("publish dir"))))
    print("\tpubishing:\t"+str(SETTINGS.get("publishing"))+"\n")

    # editor selection
    SETTINGS.update({"editor": select_editor()})
    redraw("text editor set to: "+SETTINGS["editor"])

    # publishing selection
    SETTINGS.update({"publishing":select_publishing()})
    core.reload_ttbprc(SETTINGS)
    update_publishing()
    redraw("blog publishing: "+str(core.publishing()))

    if core.publishing():
        print("publish directory: ~"+USER+"/public_html/"+SETTINGS.get("publish dir"))

    # save settings
    ttbprc = open(TTBPRC, "w")
    ttbprc.write(json.dumps(SETTINGS, sort_keys=True, indent=2, separators=(',',':')))
    ttbprc.close()

    raw_input("\nyou're all good to go, "+chatter.say("friend")+"! hit <enter> to continue.\n\n")
    redraw()

    return SETTINGS
Beispiel #24
0
def update_version():
    '''
    updates user to current version
    '''

    global SETTINGS

    versionFile = os.path.join(PATH, "version")

    print("ttbp had some updates!")

    print("\ngive me a second to update you to version "+__version__+"...\n")

    time.sleep(1)
    print("...")
    time.sleep(2)

    userVersion = ""

    if not os.path.isfile(versionFile):
        # from 0.8.5 to 0.8.6:

        # change style.css location
        if os.path.isfile(os.path.join(WWW, "style.css")):
            subprocess.call(["mv", os.path.join(WWW, "style.css"), CONFIG])

        # change www symlink
        if os.path.exists(WWW):
            subprocess.call(["rm", WWW])
        
        subprocess.call(["mkdir", WWW])

        subprocess.call(["ln", "-s", os.path.join(CONFIG, "style.css"), os.path.join(WWW, "style.css")])

        publishDir = os.path.join(PUBLIC, SETTINGS.get("publish dir"))
        if os.path.exists(publishDir):
            subprocess.call(["rm", "-rf", publishDir])

        subprocess.call(["ln", "-s", WWW, os.path.join(PUBLIC, SETTINGS.get("publish dir"))])

        # repopulate html files
        core.load_files()
        core.write("index.html")

        # add publishing setting
        print("\nnew feature!\n")
        SETTINGS.update({"publishing":select_publishing()})
        update_publishing()
        ttbprc = open(TTBPRC, "w")
        ttbprc.write(json.dumps(SETTINGS, sort_keys=True, indent=2, separators=(',',':')))
        ttbprc.close()

    else: # version at least 0.8.6
        userVersion = open(versionFile, "r").read().rstrip()

        # from 0.8.6
        if userVersion == "0.8.6":
            print("\nresetting your publishing settings...\n")
            SETTINGS.update({"publishing":select_publishing()})
            update_publishing()
            ttbprc = open(TTBPRC, "w")
            ttbprc.write(json.dumps(SETTINGS, sort_keys=True, indent=2, separators=(',',':')))
            ttbprc.close()

    # increment user versionfile
    open(versionFile, "w").write(__version__)
    print("""
you're all good to go, """+chatter.say("friend")+"""! please contact ~endorphant if
somehing strange happened to you during this update.
""")

    # show patch notes
    if userVersion != "0.9.0" and userVersion != "0.9.0b":
        # version 0.9.0 patch notes:
        print("""
ver. 0.9.0 features:
    * browsing other people's feels from neighbor view
    * documentation browser
        """)

    # version 0.9.1 patch notes
    print("""
ver 0.9.1 features:
    * graffiti wall
    """)
Beispiel #25
0
def stop():
    return "\n\n\t"+chatter.say("bye")+"\n\n"
Beispiel #26
0
    def handle(self, msg):
        '''
        Main message handler. Reponds to ping if server pings; otherwise,
        parses incoming message and handles it appropriately.

        If the message was a PM, responds in that PM.

        If the message was from the bot owner, call admin_panel() before
        proceeding.
        '''

        msg = msg.strip('\n\r')

        print("< "+msg)

        if re.match("^PING", msg):
            return self.ping("pong")

        msg = msg.strip('\n\r')
        parsed = ircformatter.parse_dict(msg)

        ## actions on join
        if parsed.get("command") == "JOIN":
            self.multisay(
                    parsed.get("channel"),
                    cndorphbot.seen(parsed.get("channel"), parsed.get("nick")),
                    parsed.get("nick")
                    )

        if parsed.get("command") == "MODE":
            if re.match("\+o "+self.BOTNAME, parsed.get("message")):
                self.say(parsed.get("channel"), chatter.say("affection"))

        ## actions on ACTION
        if len(parsed.get("message", "").split("ACTION")) > 1:
            response = cndorphbot.did(
                    parsed.get("channel"),
                    parsed.get("nick"),
                    " ".join(parsed.get("message").split("ACTION ")[1:])
                    )
            if len(response) > 0:
                self.multisay(
                        parsed.get("channel"),
                        response,
                        parsed.get("nick")
                        )

        ## actions on privmsg
        if parsed.get("command") == "PRIVMSG":
            ## if this is a PM, switch channel for outgoing message
            if parsed.get("channel") == self.BOTNAME:
                parsed.update({"channel":parsed.get("nick")})

            ## catch admin command
            if parsed.get("nick") == self.ADMIN:
                code = self.admin_panel(parsed.get("channel"), parsed.get("nick"), parsed.get("time"), parsed.get("message"))
                if code:
                   return

            if parsed.get("message").find(self.BOTNAME+": ") != -1 or self.is_pm(parsed):
                # put stuff here for direct address
                self.multisay(
                        parsed.get("channel"),
                        cndorphbot.addressed(parsed.get("channel"), parsed.get("nick"), parsed.get("time"), parsed.get("message")),
                        parsed.get("nick")
                        )
            else:
                # general responses
                self.multisay(parsed.get("channel"), cndorphbot.said(parsed.get("channel"), parsed.get("nick"), parsed.get("time"), parsed.get("message")), random.choice([parsed.get("nick"), ""]))

        sys.stdout.flush()
Beispiel #27
0
def update_version():
    '''
    updates user to current version
    '''

    global SETTINGS

    versionFile = os.path.join(PATH, "version")

    print("ttbp had some updates!")

    print("\ngive me a second to update you to version "+__version__+"...\n")

    time.sleep(1)
    print("...")
    time.sleep(2)

    userVersion = ""

    if not os.path.isfile(versionFile):
        # from 0.8.5 to 0.8.6:

        # change style.css location
        if os.path.isfile(os.path.join(WWW, "style.css")):
            subprocess.call(["mv", os.path.join(WWW, "style.css"), CONFIG])

        # change www symlink
        if os.path.exists(WWW):
            subprocess.call(["rm", WWW])
        
        subprocess.call(["mkdir", WWW])

        subprocess.call(["ln", "-s", os.path.join(CONFIG, "style.css"), os.path.join(WWW, "style.css")])

        publishDir = os.path.join(PUBLIC, SETTINGS.get("publish dir"))
        if os.path.exists(publishDir):
            subprocess.call(["rm", "-rf", publishDir])

        subprocess.call(["ln", "-s", WWW, os.path.join(PUBLIC, SETTINGS.get("publish dir"))])

        # repopulate html files
        core.load_files()
        core.write("index.html")

        # add publishing setting
        print("\nnew feature!\n")
        SETTINGS.update({"publishing":select_publishing()})
        update_publishing()
        ttbprc = open(TTBPRC, "w")
        ttbprc.write(json.dumps(SETTINGS, sort_keys=True, indent=2, separators=(',',':')))
        ttbprc.close()

    else: # version at least 0.8.6
        userVersion = open(versionFile, "r").read().rstrip()

        # from 0.8.6
        if userVersion == "0.8.6":
            print("\nresetting your publishing settings...\n")
            SETTINGS.update({"publishing":select_publishing()})
            update_publishing()
            ttbprc = open(TTBPRC, "w")
            ttbprc.write(json.dumps(SETTINGS, sort_keys=True, indent=2, separators=(',',':')))
            ttbprc.close()

    # increment user versionfile
    open(versionFile, "w").write(__version__)
    print("""
you're all good to go, """+chatter.say("friend")+"""! please contact ~endorphant if
somehing strange happened to you during this update.
""")

    # show patch notes
    #if userVersion != "0.9.0" and userVersion != "0.9.0b":
    if userVersion[0:5] < "0.9.0":
        # version 0.9.0 patch notes:
        print("""
ver. 0.9.0 features:
    * browsing other people's feels from neighbor view
    * documentation browser
        """)

    if userVersion[0:5] < "0.9.1":
        # version 0.9.1 patch notes
        print("""
ver 0.9.1 features:
    * graffiti wall
        """)