<reponame>ketsushiri/res-ans<filename>auto-response/schizo/schizo.py
#!/usr/bin/env python

"""
    -- * Шизоответчик для серьёзных людей.
         https://dev.vk.com/api/user-long-poll/getting-started

    -- * Если whitelist.ini пустой, то отвечает всем подряд.
         Если нет, только конкретным человекам. Использовать только численные айдишки.

"""

import requests
from random import choice, randint

import markovify

VERS = "5.131"
CONS = 2000000000 
CONT = "oldy.txt"

def get_content(path: str) -> str:
    with open(path, "r") as f:
        return f.read()

cont = list(
        filter(
                lambda x: x != "\n" and x != "" and x != " ",
                get_content(CONT).split("\n")
            )
        )

class Void:
    pass

class Schema:
    pass

class LongPollFailed(Exception):
    def __str__(self):
        return "Failed to get long poll server."


def call_method(name: str, **kwargs) -> Schema:
    _name = "https://api.vk.com/method/%s" % name
    _params = (kwargs["params"] if "from_dict" in kwargs else kwargs)

    # set default version for vk api
    if not "v" in _params:
        _params["v"] = VERS

    return requests.get(_name, params = _params).json()


def send_response(token: str, _id: int, debug = False) -> Void:
    try:
        main_shizo = markovify.Text(choice(cont))
        local_shizo = main_shizo.make_short_sentence(250)

    except KeyError:
        local_shizo = None

    if not local_shizo:
        local_shizo = choice(cont)

    params = {
              "access_token": token, "peer_id": _id,
              "random_id": randint(1, 10**10), "message": local_shizo
              }

    if (_id < CONS):
        params["user_id"] = _id
    else:
        params["chat_id"] = _id - CONS

    resp = call_method("messages.send", from_dict = True, params = params)
    if (debug): print(resp);


class LongPoll:
    def __init__(self, token, white_list = list()):
        self.token = token

        # will mutate it locally through methods.
        self.server = str()
        self.key = str()
        self.ts  = str()

        self.whitelist = white_list

    def __get_longpoll_server(self, debug = False) -> Void:
        response = call_method("messages.getLongPollServer", access_token = self.token, lp_version = 3)
        if not "response" in response:
            raise LongPollFailed();

        resp = response["response"]
        self.server, self.key, self.ts = (resp["server"], resp["key"], resp["ts"])

    def __long_poll_request(self, debug = False) -> Void:
        link = "https://%s?act=a_check&key=%s&ts=%s&wait=50&mode=2&version=3" % (self.server, self.key, self.ts)
        response = requests.get(link).json()

        if ("failed" in response):
            self.ts = (response["new_ts"] if response["failed"] == 1 else "failed")
            return

        updates = response["updates"]
        if (debug): print(updates);

        for update in updates:
            # 4 => new message.
            # second bit in flag is 1 => we are sending msg => ignore.
            if update[0] == 4 and not (2 & update[2]):
                if not len(self.whitelist) or update[3] in self.whitelist:
                    send_response(self.token, update[3], debug = True)

        # update ts
        self.ts = response["ts"]

    def main_loop(self, debug = False) -> Void:
        self.__get_longpoll_server(debug = debug)
        while 1:
            self.__long_poll_request(debug = debug)
            if self.ts == "failed":
                self.__get_longpoll_server(debug = debug)


def digit_predicate(string: str) -> bool:
    check_list = list("1234567890")
    for i in string:
        if not i in check_list:
            return False

    return True


def main_loop(token_path: str) -> Void:
    token = get_content(token_path)
    if (token.endswith("\n")):
        token = token[:-1]

    whitelist = list(
                     filter(
                             lambda x: digit_predicate(x) and x != '',
                             get_content("whitelist.ini").split("\n")
                           )
                    )
    whitelist = list(map(int, whitelist))
    lp = LongPoll(token, white_list = whitelist)
    lp.main_loop()


if __name__ == "__main__":
    main_loop("token.ini")

