def test_message_sender(pickle_rick):
    chatcommunicate._last_messages = chatcommunicate.LastMessages({}, collections.OrderedDict())

    threading.Thread(target=chatcommunicate.send_messages, daemon=True).start()

    room = chatcommunicate.RoomData(Mock(), -1, False)

    room.room.id = 11540
    room.room._client.host = "stackexchange.com"

    room.room._client._do_action_despite_throttling.return_value = Fake({"json": lambda: {"id": 1}})
    chatcommunicate._msg_queue.put((room, "test", None))

    while not chatcommunicate._msg_queue.empty():
        time.sleep(0)

    room.room._client._do_action_despite_throttling.assert_called_once_with(("send", 11540, "test"))
    room.room.reset_mock()
    assert chatcommunicate._last_messages.messages[("stackexchange.com", 11540)] == collections.deque((1,))

    room.room.id = 30332
    room.room._client._do_action_despite_throttling.return_value = Fake({"json": lambda: {"id": 2}})
    chatcommunicate._msg_queue.put((room, "test", "did you hear about what happened to pluto"))

    while not chatcommunicate._msg_queue.empty():
        time.sleep(0)

    room.room._client._do_action_despite_throttling.assert_called_once_with(("send", 30332, "test"))
    assert chatcommunicate._last_messages.messages[("stackexchange.com", 11540)] == collections.deque((1,))
    assert chatcommunicate._last_messages.reports == collections.OrderedDict({("stackexchange.com", 2): "did you hear about what happened to pluto"})
Exemplo n.º 2
0
    def wrap_watch(pattern, force=False):
        cmd = 'watch{0}'.format('-force' if force else '')
        msg = Fake({
            "_client": {
                "host": "stackexchange.com",
                "get_user": lambda id: Fake({
                    "name": "J F",
                    "id": id
                })
            },
            "owner": {
                "name": "El'endia Starman",
                "id": 1
            },
            "room": {
                "id": 11540,
                "get_current_user_ids": lambda: [161943]
            },
            # Ouch, this is iffy
            # Prevent an error from deep inside do_blacklist
            "content_source": '!!/{0} {1}'.format(cmd, pattern)
        })
        msg.room._client = msg._client

        return chatcommands.watch(pattern, alias_used=cmd, original_msg=msg)
def test_bisect(command, test_text, expected_result):
    chatcommunicate.parse_room_config("test/test_rooms.yml")
    msg = Fake({
        "owner": {
            "name": "ArtOfCode",
            "id": 121520,
            "is_moderator": True
        },
        "room": {
            "_client": {
                "host": "stackexchange.com"
            },
            "id": 11540
        },
        "content_source": None
    })

    msg.content_source = "!!/{} {}".format(command, test_text)
    print('command:', command)
    print('test_text:', test_text)
    msg.content = msg.content_source
    # All of the substitution references used in the .format() for the expected result are named. Any which are numbers are
    # part of the expected results.
    expected_result = regex.sub(r"(\{\d+(?:,\d+)?\})", r'{\1}',
                                expected_result)
    formatted_expected_result = expected_result.format(
        test_text=test_text,
        bot_repo_slug=GlobalVars.bot_repo_slug,
        commit_id=GlobalVars.commit.id)
    chat_command = getattr(chatcommands, command)
    result = chat_command(None, original_msg=msg)
    print('formatted_expected_result:', formatted_expected_result)
    print('                   result:', result)
    assert result == formatted_expected_result
Exemplo n.º 4
0
def test_blame():
    msg1 = Fake({
        "_client": {
            "host": "stackexchange.com",
            "get_user": lambda id: Fake({
                "name": "J F",
                "id": id
            })
        },
        "room": {
            "get_current_user_ids": lambda: [161943]
        }
    })

    assert chatcommands.blame(
        original_msg=msg1
    ) == "It's [J F](https://chat.stackexchange.com/users/161943)'s fault."

    msg2 = Fake({
        "_client": {
            "host": "stackexchange.com",
            "get_user": lambda id: Fake({
                "name": "J F",
                "id": id
            })
        }
    })

    assert chatcommands.blame2(
        "\u200B\u200C\u2060\u200D\u180E\uFEFF\u2063", original_msg=msg2
    ) == "It's [J F](https://chat.stackexchange.com/users/161943)'s fault."
Exemplo n.º 5
0
def test_bisect():
    chatcommunicate.parse_room_config("test/test_rooms.yml")
    msg = Fake({
        "owner": {
            "name": "ArtOfCode",
            "id": 121520,
            "is_moderator": True
        },
        "room": {
            "_client": {
                "host": "stackexchange.com"
            },
            "id": 11540
        },
        "content_source": None
    })
    msg.content_source = "!!/bisect :::essayssos.com:::"
    assert chatcommands.bisect(
        None, original_msg=msg
    ) == r"Matched by `essayssos\.com` on [line 1 of watched_keywords.txt](https://github.com/{}/blob/{}/watched_keywords.txt#L1)".format(
        GlobalVars.bot_repo_slug, GlobalVars.commit.id)
    msg.content_source = "!!/bisect OoOasdfghjklOoO"
    assert chatcommands.bisect(
        None, original_msg=msg
    ) == r"'OoOasdfghjklOoO' is not caught by a blacklist or watchlist item."
Exemplo n.º 6
0
Arquivo: PoT.py Projeto: xtenex/PoT
def main():
    try:
        auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
        auth.set_access_token(access_key, access_secret)
        auth.get_authorization_url()
        api = tweepy.API(auth)
    except tweepy.TweepError:
        print('Error')

    username = sys.argv[1]
    user = api.get_user(username)

    target = Fake(user)
    target.getMentions(api)
    spoofAccount = input("Select account: ")
    url = input("Phising URL: ")
    print("\n\n")

    spoofAc = Fake(api.get_user(spoofAccount))
    spoofAc.spoofProfile(api)

    tweets = spoofAc.getTweets(api)
    fakeTweetGenerator = TweetGenerator(tweets)
    fakeTweet = fakeTweetGenerator.setup(tweets)
    fakeTweet = ".@{} {} {} .".format(username, fakeTweet, url)

    print("\n***********************")
    print("This fake tweet has been sent:")
    print(colored(fakeTweet, 'green'))
    print("***********************")

    api.update_status(fakeTweet)  # send tweet
def test_message_type():
    fake1 = Fake({}, spec=chatcommunicate.Message)
    assert chatcommands.message(fake1) == fake1

    fake2 = Fake({})
    threw_exception = False

    try:
        chatcommands.message(fake2)
    except AssertionError:
        threw_exception = True

    assert threw_exception
Exemplo n.º 8
0
def test_inqueue():
    site = Fake({"keys": (lambda: ['1'])})

    class FakeQueue:
        def __getitem__(self, _):
            return site

        def __contains__(self, name):
            return name == "codegolf.stackexchange.com"

    chatcommands.GlobalVars.bodyfetcher = Fake({"queue": FakeQueue()})

    assert chatcommands.inqueue("https://codegolf.stackexchange.com/a/1") == "Can't check for answers."
    assert chatcommands.inqueue("https://stackoverflow.com/q/1") == "Not in queue."
    assert chatcommands.inqueue("https://codegolf.stackexchange.com/q/1") == "#1 in queue."
Exemplo n.º 9
0
def test_metasmoke():
    msg = Fake({
        "owner": {
            "name": "ArtOfCode",
            "id": 121520,
            "is_moderator": False
        },
        "room": {
            "id": 11540,
            "_client": {
                "host": "stackexchange.com"
            }
        },
        "_client": {
            "host": "stackexchange.com"
        }
    })
    msg_source = "metasmoke is {}. Current failure count: {} " + "({id})".format(id=GlobalVars.location)

    assert chatcommands.metasmoke(original_msg=msg, alias_used="ms-up") == "metasmoke is now considered up."
    assert chatcommands.metasmoke(original_msg=msg, alias_used="ms-status") == msg_source.format("up", 0)
    assert chatcommands.metasmoke(original_msg=msg, alias_used="ms-down") == "metasmoke is now considered down."
    assert chatcommands.metasmoke(original_msg=msg, alias_used="ms-status") == msg_source.format("down", 999)
    assert chatcommands.metasmoke(original_msg=msg, alias_used="ms-up") == "metasmoke is now considered up."
    assert chatcommands.metasmoke(original_msg=msg, alias_used="ms-status") == msg_source.format("up", 0)
Exemplo n.º 10
0
def test_approve(monkeypatch):
    msg = Fake({
        "_client": {
            "host": "stackexchange.com",
        },
        "id": 88888888,
        "owner": {
            "name": "ArtOfCode",
            "id": 121520
        },
        "room": {
            "id": 11540,
            "name": "Continuous Integration",
            "_client": None
        },
        "content_source": '!!/approve 8888',
    })
    msg.room._client = msg._client

    # Prevent from attempting to check privileges with Metasmoke
    monkeypatch.setattr(GlobalVars, "code_privileged_users", [])
    assert chatcommands.approve(
        8888, original_msg=msg).startswith("You need code privileges")

    monkeypatch.setattr(GlobalVars, "code_privileged_users",
                        [('stackexchange.com', 121520)])
    with monkeypatch.context() as m:
        # Oh no GitHub is down
        m.setattr("requests.get", lambda *args, **kwargs: None)
        assert chatcommands.approve(
            8888, original_msg=msg) == "Cannot connect to GitHub API"
    assert chatcommands.approve(
        2518, original_msg=msg).startswith("PR #2518 is not created by me")
Exemplo n.º 11
0
def test_coffee():
    msg = Fake({"owner": {"name": "El'endia Starman"}})

    assert chatcommands.coffee(
        None, original_msg=msg) == "*brews coffee for @El'endiaStarman*"
    assert chatcommands.coffee(
        "angussidney") == "*brews coffee for @angussidney*"
def test_metasmoke():
    chatcommunicate.parse_room_config("test/test_rooms.yml")
    orig_tell_rooms_with = chatcommunicate.tell_rooms_with
    chatcommunicate.tell_rooms_with = dummy_tell_rooms_with
    msg = Fake({
        "owner": {
            "name": "ArtOfCode",
            "id": 121520,
            "is_moderator": False
        },
        "room": {
            "id": 11540,
            "_client": {
                "host": "stackexchange.com"
            }
        },
        "_client": {
            "host": "stackexchange.com"
        }
    })
    msg_source = "metasmoke is {}. Current failure count: {} " + "({id})".format(
        id=GlobalVars.location)

    chatcommands.metasmoke(original_msg=msg, alias_used="ms-up")
    assert GlobalVars.MSStatus.is_up()
    chatcommands.metasmoke(original_msg=msg, alias_used="ms-down")
    assert GlobalVars.MSStatus.is_down()
    GlobalVars.MSStatus.reset_ms_status()
    assert chatcommands.metasmoke(original_msg=msg,
                                  alias_used="ms-status") == msg_source.format(
                                      "up", 0)
    chatcommunicate.tell_rooms_with = orig_tell_rooms_with
Exemplo n.º 13
0
def test_privileged():
    chatcommunicate.parse_room_config("test/test_rooms.yml")

    msg = Fake({
        "owner": {
            "name": "El'endia Starman",
            "id": 1,
            "is_moderator": False
        },
        "room": {
            "_client": {
                "host": "stackexchange.com"
            },
            "id": 11540
        }
    })

    assert chatcommands.amiprivileged(
        original_msg=msg) == "\u2713 You are a privileged user."

    msg.owner.id = 2
    assert chatcommands.amiprivileged(
        original_msg=msg) == "\u2573 " + GlobalVars.not_privileged_warning

    msg.owner.is_moderator = True
    assert chatcommands.amiprivileged(
        original_msg=msg) == "\u2713 You are a privileged user."
Exemplo n.º 14
0
def main():
    try:
        config = configparser.RawConfigParser()
        config.read(os.path.join(os.path.dirname(__file__), 'PoT.cfg'))
        consumer_key = config.get('twitter_api', 'consumer_key')
        consumer_secret = config.get('twitter_api', 'consumer_secret')
        access_token_key = config.get('twitter_api', 'access_token_key')
        access_token_secret = config.get('twitter_api', 'access_token_secret')

        parser = argparse.ArgumentParser(description='Phishing on Twitter')
        parser.add_argument('-u', '--username', help='username to phish with ')
        args = parser.parse_args()

        try:
            auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
            auth.set_access_token(access_token_key, access_token_secret)
            auth.get_authorization_url()
            api = tweepy.API(auth)
        except tweepy.TweepError:
            print(bad + 'Authentication Error')
            exit(1)

        if args.username:
            username = args.username
        else:
            print("There is a mistake about username")
        user = api.get_user(username)

        target = Fake(user)
        target.getMentions(api)
        spoofAccount = input(que + "Select account: ")
        url = input(que + "Phishing URL: ")
        print(hardreturn * 2)

        spoofAc = Fake(api.get_user(spoofAccount))
        spoofAc.spoofProfile(api)

        tweets = spoofAc.getTweets(api)
        fakeTweetGenerator = TweetGenerator(tweets)
        fakeTweet = fakeTweetGenerator.setup(tweets)
        fakeTweet = ".@{} {} {} .".format(username, fakeTweet, url)

        print(hardreturn)
        print("***********************")
        print("This fake tweet has been sent:")
        print(colored(fakeTweet, 'green'))
        print("***********************")

        api.update_status(fakeTweet)  # send tweet
    except Exception as e:
        print(bad + str(e))
Exemplo n.º 15
0
def test_tea():
    msg = Fake({"owner": {"name": "El'endia Starman"}})

    teas = "\*brews a cup of ({}) tea for ".format("|".join(chatcommands.TEAS))
    assert regex.match(teas + "@El'endiaStarman\*",
                       chatcommands.tea(None, original_msg=msg))
    assert regex.match(teas + "@angussidney\*",
                       chatcommands.tea("angussidney"))
Exemplo n.º 16
0
def test_coffee():
    msg = Fake({"owner": {"name": "El'endia Starman"}})

    coffees = "\\*brews a cup of ({}) for ".format("|".join(
        chatcommands.COFFEES))
    assert regex.match(coffees + "@El'endiaStarman\\*",
                       chatcommands.coffee(None, original_msg=msg))
    assert regex.match(coffees + "@angussidney\\*",
                       chatcommands.coffee("angussidney"))
Exemplo n.º 17
0
class Command(BaseCommand):
	args = '< n >'
	help = 'Write how many data do you want to add'
	
	def __init__(self):
		self.fake = Fake()
		
		for i in range(1, 10):
			self.fake.arr.append(' ')

	def handle(self, *args, **options):
		n = int(args[0])
		for i in range(1, n):
			title = self.fake.text(random.randint(10, 40))
			content = self.fake.text(random.randint(500, 1500))
			topic = Topic.objects.get(id = int(random.randint(1, Topic.objects.count())))
			user = User.objects.get(id = int(random.randint(1, User.objects.count())))
			date = self.fake.rdate()
			q = Question(title = title, content = content, topic = topic, user = user, date = date)
			q.save()
Exemplo n.º 18
0
def test_bisect():
    chatcommunicate.parse_room_config("test/test_rooms.yml")
    msg = Fake({
        "owner": {
            "name": "ArtOfCode",
            "id": 121520,
            "is_moderator": True
        },
        "room": {
            "_client": {
                "host": "stackexchange.com"
            },
            "id": 11540
        },
        "content_source": None
    })
    msg.content_source = "!!/bisect :::essayssos.com:::"
    assert chatcommands.bisect(None, original_msg=msg) == r"Matched by `essayssos\.com` on [line 1 of watched_keywords.txt](https://github.com/Charcoal-SE/SmokeDetector/blob/{}/watched_keywords.txt#L1)".format(GlobalVars.commit.id)
    msg.content_source = "!!/bisect OoOasdfghjklOoO"
    assert chatcommands.bisect(None, original_msg=msg) == r"'OoOasdfghjklOoO' is not caught by a blacklist or watchlist item."
Exemplo n.º 19
0
class Command(BaseCommand):
	args = '< n >'
	help = 'Write how many data do you want to add'
	
	def __init__(self):
		self.fake = Fake()
		
		for i in range(1, 10):
			self.fake.arr.append(' ')

	def handle(self, *args, **options):
		n = int(args[0])
		m = User.objects.all().count()
		qn = Question.objects.all().count()
		for i in range(1, n):
			try:
				qst = Question.objects.get(id = int(random.randint(1, qn)))
				qc = QComments(content = self.fake.text(random.randint(50, 500)), date = self.fake.rdate(), user = User.objects.get(id = int(random.randint(1, m))), qst = qst)
				qc.save()
			except(User.DoesNotExist, Question.DoesNotExist):
				print("No")
Exemplo n.º 20
0
class Command(BaseCommand):
	args = '< n >'
	help = 'Write how many data do you want to add'
	
	def __init__(self):
		self.fake = Fake()
		
		for i in range(1, 10):
			self.fake.arr.append(' ')
		
	def handle(self, *args, **options):
		n = int(args[0])
		qn = Question.objects.count()
		qu = User.objects.count()
		for i in range(1, n):
			user = User.objects.get(id = random.randint(1, qu))
			try:
				a = Answer(content = self.fake.text(random.randint(50, 400)), qst = Question.objects.get(id = random.randint(1, qn)), 
									user = user, date = self.fake.date(user.reg_date.month, user.reg_date.year), flag = False, raiting=0)
				a.save()
			except Question.DoesNotExist:
				print("Question does not exist")
Exemplo n.º 21
0
def test_report(handle_spam):
    try:
        msg = Fake({
            "owner": {
                "name": "El'endia Starman",
                "id": 1,
                "is_moderator": False
            },
            "room": {
                "id": 11540,
                "name": "Charcoal HQ",
                "_client": {
                    "host": "stackexchange.com"
                }
            },
            "_client": {
                "host": "stackexchange.com"
            },
            "id": 1337
        })

        assert chatcommands.report("test", original_msg=msg) == "Post 1: That does not look like a valid post URL."

        assert chatcommands.report("one two three four five plus-an-extra", original_msg=msg) == (
            "To avoid SmokeDetector reporting posts too slowly, you can report at most 5 posts at a time. This is to avoid "
            "SmokeDetector's chat messages getting rate-limited too much, which would slow down reports."
        )

        assert chatcommands.report('http://stackoverflow.com/q/1', original_msg=msg) == \
            "Post 1: Could not find data for this post in the API. It may already have been deleted."

        # Valid post
        assert chatcommands.report('http://stackoverflow.com/a/1732454', original_msg=msg) is None

        _, call = handle_spam.call_args_list[0]
        assert isinstance(call["post"], Post)
        assert call["reasons"] == ["Manually reported answer"]
        assert call["why"] == "Post manually reported by user *El'endia Starman* in room *Charcoal HQ*.\n"

        # Don't re-report
        GlobalVars.latest_questions = [('stackoverflow.com', '1732454', 'RegEx match open tags except XHTML self-contained tags')]
        assert chatcommands.report('http://stackoverflow.com/a/1732454', original_msg=msg).startswith("Post 1: Already recently "
                                                                                                      "reported")

        # Can use report command multiple times in 30s if only one URL was used
        assert chatcommands.report('http://stackoverflow.com/q/1732348', original_msg=msg) is None
    finally:
        GlobalVars.blacklisted_users = []
        GlobalVars.latest_questions = []
Exemplo n.º 22
0
def test_checkpost(handle_spam):
    try:
        msg = Fake({
            "owner": {
                "name": "foo",
                "id": 1,
                "is_moderator": False
            },
            "room": {
                "id": 11540,
                "name": "Charcoal HQ",
                "_client": {
                    "host": "stackexchange.com"
                }
            },
            "_client": {
                "host": "stackexchange.com"
            },
            "id": 1337
        })

        assert chatcommands.checkpost("foo", original_msg=msg) == "That does not look like a valid post URL."
        assert chatcommands.checkpost("https://stackoverflow.com/q/1", original_msg=msg) == \
            "Cannot find data for this post in the API. It may have already been deleted."

        # This is the highest voted question on Stack Overflow
        good_post_url = "https://stackoverflow.com/q/11227809"
        post = api_get_post(good_post_url)
        assert chatcommands.checkpost(good_post_url, original_msg=msg) == \
            "Post [{0}]({1}) does not look like spam.".format(post.title, to_protocol_relative(post.post_url))

        # This post is found in Sandbox Archive, so it will remain intact and is a reliable test post
        # backup: https://meta.stackexchange.com/a/228635
        test_post_url = "https://meta.stackexchange.com/a/209772"
        assert chatcommands.checkpost(test_post_url, original_msg=msg) is None

        _, call = handle_spam.call_args_list[0]
        assert isinstance(call["post"], Post)
        assert call["why"].endswith("Manually triggered scan")

        # Strangely it doesn't work if scanned repeatedly
    finally:
        GlobalVars.latest_questions = []
def test_reject(monkeypatch):
    chatcommunicate.parse_room_config("test/test_rooms.yml")
    msg = Fake({
        "_client": {
            "host": "stackexchange.com",
        },
        "id": 88888888,
        "owner": {
            "name": "ArtOfCode",
            "id": 121520
        },
        "room": {
            "id": 11540,
            "name": "Continuous Integration",
            "_client": None
        },
        "content_source": '!!/reject 8888',
    })
    msg.room._client = msg._client

    # Prevent from attempting to check privileges with Metasmoke
    monkeypatch.setattr(GlobalVars, "code_privileged_users", [])
    assert chatcommands.reject('8888 "test"',
                               original_msg=msg,
                               alias_used="reject").startswith(
                                   "You need blacklist manager privileges")

    monkeypatch.setattr(GlobalVars, "code_privileged_users",
                        [('stackexchange.com', 121520)])
    with monkeypatch.context() as m:
        # Oh no GitHub is down
        original_get = requests.get
        m.setattr("requests.get", lambda *args, **kwargs: None)
        assert chatcommands.reject(
            '8888 "test"', original_msg=msg,
            alias_used="reject-force") == "Cannot connect to GitHub API"
        m.setattr("requests.get", original_get)
    assert chatcommands.reject('2518 "test"',
                               original_msg=msg,
                               alias_used="close").startswith("Please provide")
Exemplo n.º 24
0
def test_metasmoke():
    msg = Fake({
        "owner": {
            "name": "El'endia Starman",
            "id": 1,
            "is_moderator": False
        },
        "room": {
            "id": 11540,
            "_client": {
                "host": "stackexchange.com"
            }
        },
        "_client": {
            "host": "stackexchange.com"
        }
    })
    msg_source = "metasmoke is {}. Current failure count: {}"

    assert chatcommands.metasmoke(
        original_msg=msg,
        alias_used="ms-up") == "metasmoke is now considered up."
    assert chatcommands.metasmoke(original_msg=msg,
                                  alias_used="ms-status") == msg_source.format(
                                      "up", 0)
    assert chatcommands.metasmoke(
        original_msg=msg,
        alias_used="ms-down") == "metasmoke is now considered down."
    assert chatcommands.metasmoke(original_msg=msg,
                                  alias_used="ms-status") == msg_source.format(
                                      "down", 999)
    assert chatcommands.metasmoke(
        original_msg=msg,
        alias_used="ms-up") == "metasmoke is now considered up."
    assert chatcommands.metasmoke(original_msg=msg,
                                  alias_used="ms-status") == msg_source.format(
                                      "up", 0)
Exemplo n.º 25
0
def load_fakes(fakes_list, fakes_path, originals_path):
    """
    method loads images into Image structure
    """
    data = []
    to_remove = []
    for i, item in enumerate(fakes_list):
        #get originals names
        parametres = item.split('_')

        #load fake
        fake = cv2.imread(os.path.join(fakes_path, item), -1)

        #load original
        original = cv2.imread(
            os.path.join(
                originals_path,
                "Au_" + parametres[4][:3] + "_" + parametres[4][3:] + ".jpg"),
            -1)

        #try - check if images have same dimension
        try:
            x, y, w, h = get_ground_truth(fake, original)
        except:
            to_remove.append(item)
            continue

        #load into required structure
        dato = Fake(fake, os.path.join(fakes_path, item), True, x, y, w, h)
        data.append(dato)

    #weird fakes, which does not correspond to naming protocol
    for i, item in enumerate(to_remove):
        print("Bad input: {}".format(item))

    return data
Exemplo n.º 26
0
def test_notifications():
    try:
        msg1 = Fake({
            "owner": {
                "name": "El'endia Starman",
                "id": 1,
                "is_moderator": False
            },
            "room": {
                "id": 11540,
                "_client": {
                    "host": "stackexchange.com"
                }
            },
            "_client": {
                "host": "stackexchange.com"
            }
        })

        msg2 = Fake({
            "owner": {
                "name": "angussidney",
                "id": 145827,
                "is_moderator": False
            },
            "room": {
                "id": 11540,
                "_client": {
                    "host": "stackexchange.com"
                }
            },
            "_client": {
                "host": "stackexchange.com"
            }
        })

        # User 1
        assert chatcommands.allnotificationsites("11540", original_msg=msg1) == \
            "You won't get notified for any sites in that room."
        assert chatcommands.willbenotified("11540", "gaming", original_msg=msg1) == \
            "No, you won't be notified for that site in that room."
        assert chatcommands.notify("11540", "gaming", None, original_msg=msg1) == \
            "You'll now get pings from me if I report a post on `gaming`, in room `11540` on `chat.stackexchange.com`"
        assert chatcommands.notify("11540", "codegolf.stackexchange.com", None, original_msg=msg1) == \
            "You'll now get pings from me if I report a post on `codegolf.stackexchange.com`, in room `11540` on " \
            "`chat.stackexchange.com`"
        assert chatcommands.willbenotified("11540", "gaming.stackexchange.com", original_msg=msg1) == \
            "Yes, you will be notified for that site in that room."
        assert chatcommands.willbenotified("11540", "codegolf", original_msg=msg1) == \
            "Yes, you will be notified for that site in that room."

        # User 2
        assert chatcommands.allnotificationsites("11540", original_msg=msg2) == \
            "You won't get notified for any sites in that room."
        assert chatcommands.willbenotified("11540", "raspberrypi", original_msg=msg2) == \
            "No, you won't be notified for that site in that room."
        assert chatcommands.notify("11540", "raspberrypi", None, original_msg=msg2) == \
            "You'll now get pings from me if I report a post on `raspberrypi`, in room `11540` on `chat.stackexchange.com`"
        assert chatcommands.notify("11540", "raspberrypi", None, original_msg=msg2) == \
            "That notification configuration is already registered."
        assert chatcommands.willbenotified("11540", "raspberrypi.stackexchange.com", original_msg=msg2) == \
            "Yes, you will be notified for that site in that room."

        # Check for no interaction
        assert chatcommands.allnotificationsites("11540", original_msg=msg1) == \
            "You will get notified for these sites:\r\ncodegolf.stackexchange.com, gaming.stackexchange.com"
        assert chatcommands.allnotificationsites("11540", original_msg=msg2) == \
            "You will get notified for these sites:\r\nraspberrypi.stackexchange.com"

        # Remove all notifications and check
        assert chatcommands.unnotify("11540", "gaming.stackexchange.com", original_msg=msg1) == \
            "I will no longer ping you if I report a post on `gaming.stackexchange.com`, in room `11540` on " \
            "`chat.stackexchange.com`"
        assert chatcommands.unnotify("11540", "codegolf", original_msg=msg1) == \
            "I will no longer ping you if I report a post on `codegolf`, in room `11540` on `chat.stackexchange.com`"
        assert chatcommands.unnotify("11540", "raspberrypi", original_msg=msg2) == \
            "I will no longer ping you if I report a post on `raspberrypi`, in room `11540` on `chat.stackexchange.com`"
        assert chatcommands.unnotify("11540", "raspberrypi", original_msg=msg2) == \
            "That configuration doesn't exist."
        assert chatcommands.allnotificationsites("11540", original_msg=msg1) == \
            "You won't get notified for any sites in that room."
        assert chatcommands.willbenotified("11540", "raspberrypi", original_msg=msg2) == \
            "No, you won't be notified for that site in that room."

        assert chatcommands.allnotificationsites(
            "asdf",
            original_msg=msg1) == "Invalid input type given for an argument"
        assert chatcommands.notify("11540", "charcoalspam.stackexchange.com", None, original_msg=msg1) == \
            "The given SE site does not exist."

        assert chatcommands.notify("11540", "codegolf", "True", original_msg=msg1) == \
            "You'll now get pings from me if I report a post on `codegolf`, in room `11540` on `chat.stackexchange.com`"
        assert chatcommands.notify("11540", "codegolf", "False", original_msg=msg1) == \
            "That notification configuration is already registered."
    finally:
        # Cleanup
        _remove_pickle("notifications.p")
Exemplo n.º 27
0
def test_whitelisted_users():
    try:
        msg = Fake({
            "owner": {
                "name": "El'endia Starman",
                "id": 1,
                "is_moderator": False
            },
            "room": {
                "id": 11540,
                "_client": {
                    "host": "stackexchange.com"
                }
            },
            "_client": {
                "host": "stackexchange.com"
            }
        })

        # Format: !!/*wlu profileurl
        assert chatcommands.iswlu("http://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User is not whitelisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.addwlu("http://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User whitelisted (`4622463` on `stackoverflow.com`)."
        # TODO: Add test here as well
        assert chatcommands.iswlu("http://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User is whitelisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.rmwlu("http://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User removed from whitelist (`4622463` on `stackoverflow.com`)."
        assert chatcommands.iswlu("http://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User is not whitelisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.rmwlu("http://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User is not whitelisted."

        # Format: !!/*wlu userid sitename
        assert chatcommands.iswlu("4622463 stackoverflow", original_msg=msg) == \
            "User is not whitelisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.addwlu("4622463 stackoverflow", original_msg=msg) == \
            "User whitelisted (`4622463` on `stackoverflow.com`)."
        # TODO: Add test here as well
        assert chatcommands.iswlu("4622463 stackoverflow", original_msg=msg) == \
            "User is whitelisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.rmwlu("4622463 stackoverflow", original_msg=msg) == \
            "User removed from whitelist (`4622463` on `stackoverflow.com`)."
        assert chatcommands.iswlu("4622463 stackoverflow", original_msg=msg) == \
            "User is not whitelisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.rmwlu("4622463 stackoverflow", original_msg=msg) == \
            "User is not whitelisted."

        # Invalid input
        assert chatcommands.addwlu("http://meta.stackexchange.com/users", original_msg=msg) == \
            "Invalid format. Valid format: `!!/addwlu profileurl` *or* `!!/addwlu userid sitename`."
        assert chatcommands.rmwlu("http://meta.stackexchange.com/", original_msg=msg) == \
            "Invalid format. Valid format: `!!/rmwlu profileurl` *or* `!!/rmwlu userid sitename`."
        assert chatcommands.iswlu("msklkldsklaskd", original_msg=msg) == \
            "Invalid format. Valid format: `!!/iswlu profileurl` *or* `!!/iswlu userid sitename`."

        # Invalid sitename
        assert chatcommands.addwlu("1 completelyfakesite", original_msg=msg) == \
            "Error: Could not find the given site."
        assert chatcommands.iswlu("1 completelyfakesite", original_msg=msg) == \
            "Error: Could not find the given site."
    except:
        # Cleanup
        _remove_pickle("whitelistedUsers.p")
Exemplo n.º 28
0
def test_allspam(handle_spam):
    try:
        msg = Fake({
            "owner": {
                "name": "El'endia Starman",
                "id": 1,
                "is_moderator": False
            },
            "room": {
                "id": 11540,
                "name": "Charcoal HQ",
                "_client": {
                    "host": "stackexchange.com"
                }
            },
            "_client": {
                "host": "stackexchange.com"
            },
            "id": 1337
        })

        assert chatcommands.allspam(
            "test",
            original_msg=msg) == "That doesn't look like a valid user URL."

        # If this code lasts long enough to fail, I'll be happy
        assert chatcommands.allspam("http://stackexchange.com/users/10000000000", original_msg=msg) == \
            "The specified user does not appear to exist."

        assert chatcommands.allspam(
            "http://stackexchange.com/users/5869449", original_msg=msg
        ) == (
            "The specified user has an abnormally high number of accounts. Please consider flagging for moderator "
            "attention, otherwise use !!/report on the user's posts individually."
        )

        assert chatcommands.allspam(
            "http://stackexchange.com/users/11683", original_msg=msg
        ) == (
            "The specified user's reputation is abnormally high. Please consider flagging for moderator attention, "
            "otherwise use !!/report on the posts individually.")

        assert chatcommands.allspam(
            "http://stackoverflow.com/users/22656", original_msg=msg
        ) == (
            "The specified user's reputation is abnormally high. Please consider flagging for moderator attention, "
            "otherwise use !!/report on the posts individually.")

        assert chatcommands.allspam("http://stackexchange.com/users/12108751", original_msg=msg) == \
            "The specified user hasn't posted anything."

        assert chatcommands.allspam("http://stackoverflow.com/users/8846458", original_msg=msg) == \
            "The specified user has no posts on this site."

        # This test is for users with <100rep but >15 posts
        # If this breaks in the future because the below user eventually gets 100 rep (highly unlikely), use the following
        # data.SE query to find a new target. Alternatively, get a sock to post 16 answers in the sandbox.
        # https://stackoverflow.com/users/7052649/vibin (look for low rep but >1rep users, 1rep users are usually suspended)
        assert chatcommands.allspam(
            "http://stackoverflow.com/users/7052649", original_msg=msg
        ) == (
            "The specified user has an abnormally high number of spam posts. Please consider flagging for moderator "
            "attention, otherwise use !!/report on the posts individually.")

        # Valid user for allspam command
        assert chatcommands.allspam("http://stackexchange.com/users/12108974",
                                    original_msg=msg) is None

        assert handle_spam.call_count == 1
        _, call = handle_spam.call_args_list[0]
        assert isinstance(call["post"], Post)
        assert call["reasons"] == ["Manually reported answer"]
        assert call[
            "why"] == "User manually reported by *El'endia Starman* in room *Charcoal HQ*.\n"

        handle_spam.reset_mock()
        assert chatcommands.allspam(
            "http://meta.stackexchange.com/users/373807",
            original_msg=msg) is None

        assert handle_spam.call_count == 1
        _, call = handle_spam.call_args_list[0]
        assert isinstance(call["post"], Post)
        assert call["reasons"] == ["Manually reported answer"]
        assert call[
            "why"] == "User manually reported by *El'endia Starman* in room *Charcoal HQ*.\n"

    finally:
        GlobalVars.blacklisted_users.clear()
def test_blacklisted_users():
    chatcommunicate.parse_room_config("test/test_rooms.yml")
    try:
        msg = Fake({
            "owner": {
                "name": "ArtOfCode",
                "id": 121520,
                "is_moderator": False
            },
            "room": {
                "id": 11540,
                "_client": {
                    "host": "stackexchange.com"
                }
            },
            "_client": {
                "host": "stackexchange.com"
            },
            "id": 1337
        })

        # Format: !!/*blu profileurl
        assert chatcommands.isblu("https://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User is not blacklisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.addblu("https://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User blacklisted (`4622463` on `stackoverflow.com`)."
        # TODO: Edit command to check and not blacklist again, add test
        assert chatcommands.isblu("https://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User is blacklisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.rmblu("https://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User removed from blacklist (`4622463` on `stackoverflow.com`)."
        assert chatcommands.isblu("https://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User is not blacklisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.rmblu("https://stackoverflow.com/users/4622463/angussidney", original_msg=msg) == \
            "User is not blacklisted."

        # Format: !!/*blu userid sitename
        assert chatcommands.isblu("4622463 stackoverflow", original_msg=msg) == \
            "User is not blacklisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.addblu("4622463 stackoverflow", original_msg=msg) == \
            "User blacklisted (`4622463` on `stackoverflow.com`)."
        # TODO: Add test here as well
        assert chatcommands.isblu("4622463 stackoverflow", original_msg=msg) == \
            "User is blacklisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.rmblu("4622463 stackoverflow", original_msg=msg) == \
            "User removed from blacklist (`4622463` on `stackoverflow.com`)."
        assert chatcommands.isblu("4622463 stackoverflow", original_msg=msg) == \
            "User is not blacklisted (`4622463` on `stackoverflow.com`)."
        assert chatcommands.rmblu("4622463 stackoverflow", original_msg=msg) == \
            "User is not blacklisted."

        # Invalid input
        assert chatcommands.addblu("https://meta.stackexchange.com/users", original_msg=msg) == \
            "Invalid format. Valid format: `!!/addblu profileurl` *or* `!!/addblu userid sitename`."
        assert chatcommands.rmblu("https://meta.stackexchange.com/", original_msg=msg) == \
            "Invalid format. Valid format: `!!/rmblu profileurl` *or* `!!/rmblu userid sitename`."
        assert chatcommands.isblu("msklkldsklaskd", original_msg=msg) == \
            "Invalid format. Valid format: `!!/isblu profileurl` *or* `!!/isblu userid sitename`."

        # Invalid sitename
        assert chatcommands.addblu("1 completelyfakesite", original_msg=msg) == \
            "Error: Could not find the given site."
        assert chatcommands.isblu("1 completelyfakesite", original_msg=msg) == \
            "Error: Could not find the given site."
        assert chatcommands.rmblu("1 completelyfakesite", original_msg=msg) == \
            "Error: Could not find the given site."
    finally:
        # Cleanup
        remove_pickle("blacklistedUsers.p")
Exemplo n.º 30
0
def test_report(handle_spam):
    # Documentation: The process before scanning the post is identical regardless of alias_used.
    #   No need to supply alias_used to test that part.
    #   If no alias_used is supplied, it acts as if it's "scan"
    try:
        msg = Fake({
            "owner": {
                "name": "El'endia Starman",
                "id": 1,
                "is_moderator": False
            },
            "room": {
                "id": 11540,
                "name": "Charcoal HQ",
                "_client": {
                    "host": "stackexchange.com"
                }
            },
            "_client": {
                "host": "stackexchange.com"
            },
            "id": 1337
        })

        assert chatcommands.report(
            "test", original_msg=msg, alias_used="report"
        ) == "Post 1: That does not look like a valid post URL."

        assert chatcommands.report(
            "one two three four five plus-an-extra",
            original_msg=msg,
            alias_used="report"
        ) == (
            "To avoid SmokeDetector reporting posts too slowly, you can report at most 5 posts at a time. This is to avoid "
            "SmokeDetector's chat messages getting rate-limited too much, which would slow down reports."
        )

        # assert chatcommands.report('a a a a a "invalid"""', original_msg=msg) \
        #     .startswith("You cannot provide multiple custom report reasons.")

        assert chatcommands.report('https://stackoverflow.com/q/1', original_msg=msg) == \
            "Post 1: Could not find data for this post in the API. It may already have been deleted."

        # Valid post
        assert chatcommands.report('https://stackoverflow.com/a/1732454', original_msg=msg, alias_used="scan") == \
            "Post 1: This does not look like spam"
        assert chatcommands.report(
            'https://stackoverflow.com/a/1732454 "~o.O~"',
            original_msg=msg,
            alias_used="report") is None

        _, call = handle_spam.call_args_list[-1]
        assert isinstance(call["post"], Post)
        assert call["reasons"] == ["Manually reported answer"]
        assert call["why"] == (
            "Post manually reported by user *El'endia Starman* in room *Charcoal HQ* with reason: *~o.O~*."
            "\n\nThis post would not have been caught otherwise.")

        # Bad post
        # This post is found in Sandbox Archive, so it will remain intact and is a reliable test post
        # backup: https://meta.stackexchange.com/a/228635
        test_post_url = "https://meta.stackexchange.com/a/209772"
        assert chatcommands.report(
            test_post_url, original_msg=msg, alias_used="scan") is None

        _, call = handle_spam.call_args_list[-1]
        assert isinstance(call["post"], Post)
        assert call["why"].startswith(
            "Post manually scanned by user *El'endia Starman* in room *Charcoal HQ*."
        )

        # Now with report-force
        GlobalVars.blacklisted_users.clear()
        GlobalVars.latest_questions.clear()
        assert chatcommands.report(
            test_post_url, original_msg=msg, alias_used="report-force") is None
        _, call = handle_spam.call_args_list[-1]
        assert isinstance(call["post"], Post)
        assert call["why"].startswith(
            "Post manually reported by user *El'endia Starman* in room *Charcoal HQ*."
            "\n\nThis post would have also been caught for:")

        # Don't re-report
        GlobalVars.latest_questions = [
            ('stackoverflow.com', '1732454',
             'RegEx match open tags except XHTML self-contained tags')
        ]
        assert chatcommands.report(
            'https://stackoverflow.com/a/1732454',
            original_msg=msg).startswith("Post 1: Already recently reported")

        # Can use report command multiple times in 30s if only one URL was used
        assert chatcommands.report('https://stackoverflow.com/q/1732348',
                                   original_msg=msg,
                                   alias_used="report") is None
    finally:
        GlobalVars.blacklisted_users.clear()
        GlobalVars.latest_questions.clear()
Exemplo n.º 31
0
	def __init__(self):
		self.fake = Fake()
		
		for i in range(1, 10):
			self.fake.arr.append(' ')
def test_on_msg(get_last_messages, post_msg):
    client = Fake({"_br": {"user_id": 1337}, "host": "stackexchange.com"})

    room_data = chatcommunicate.RoomData(Mock(), -1, False)
    chatcommunicate._rooms[("stackexchange.com", 11540)] = room_data

    chatcommunicate.on_msg(Fake({},
                                spec=chatcommunicate.events.MessageStarred),
                           None)  # don't reply to events we don't care about

    msg1 = Fake(
        {
            "message": {
                "room": {
                    "id": 11540,
                },
                "owner": {
                    "id": 1,
                },
                "parent": None,
                "content": "shoutouts to simpleflips"
            }
        },
        spec=chatcommunicate.events.MessagePosted)

    chatcommunicate.on_msg(msg1, client)

    msg2 = Fake(
        {
            "message": {
                "room": {
                    "id": 11540
                },
                "owner": {
                    "id": 1337
                },
                "id": 999,
                "parent": None,
                "content": "!!/not_actually_a_command"
            }
        },
        spec=chatcommunicate.events.MessagePosted)

    chatcommunicate.on_msg(msg2, client)

    msg3 = Fake(
        {
            "message": {
                "room": {
                    "id": 11540,
                },
                "owner": {
                    "id": 1
                },
                "id": 999,
                "parent": None,
                "content": "!!/a_command"
            }
        },
        spec=chatcommunicate.events.MessagePosted)

    mock_command = Mock(side_effect=lambda *_, **kwargs: "hi"
                        if not kwargs["quiet_action"] else "")
    chatcommunicate._prefix_commands["a_command"] = (mock_command, (0, 0))

    chatcommunicate.on_msg(msg3, client)

    assert post_msg.call_count == 1
    assert post_msg.call_args_list[0][0][0][1] == ":999 hi"
    mock_command.assert_called_once_with(original_msg=msg3.message,
                                         alias_used="a_command",
                                         quiet_action=False)

    post_msg.reset_mock()
    mock_command.reset_mock()

    msg3.message.content = "!!/a_command-"
    chatcommunicate.on_msg(msg3, client)

    post_msg.assert_not_called()
    mock_command.assert_called_once_with(original_msg=msg3.message,
                                         alias_used="a_command",
                                         quiet_action=True)

    post_msg.reset_mock()
    mock_command.reset_mock()

    chatcommunicate._prefix_commands["a_command"] = (mock_command, (0, 1))
    chatcommunicate.on_msg(msg3, client)

    post_msg.assert_not_called()
    mock_command.assert_called_once_with(None,
                                         original_msg=msg3.message,
                                         alias_used="a_command",
                                         quiet_action=True)

    post_msg.reset_mock()
    mock_command.reset_mock()

    msg3.message.content = "!!/a_command 1 2 3"
    chatcommunicate.on_msg(msg3, client)

    assert post_msg.call_count == 1
    assert post_msg.call_args_list[0][0][0][1] == ":999 hi"
    mock_command.assert_called_once_with("1 2 3",
                                         original_msg=msg3.message,
                                         alias_used="a_command",
                                         quiet_action=False)

    post_msg.reset_mock()
    mock_command.reset_mock()

    chatcommunicate._prefix_commands["a_command"] = (mock_command, (1, 2))

    msg3.message.content = "!!/a_command"
    chatcommunicate.on_msg(msg3, client)

    assert post_msg.call_count == 1
    assert post_msg.call_args_list[0][0][0][1] == ":999 Too few arguments."
    mock_command.assert_not_called()

    post_msg.reset_mock()
    mock_command.reset_mock()

    msg3.message.content = "!!/a_command 1 2 oatmeal"
    chatcommunicate.on_msg(msg3, client)

    assert post_msg.call_count == 1
    assert post_msg.call_args_list[0][0][0][1] == ":999 Too many arguments."
    mock_command.assert_not_called()

    post_msg.reset_mock()
    mock_command.reset_mock()

    msg3.message.content = "!!/a_command- 1 2"
    chatcommunicate.on_msg(msg3, client)

    post_msg.assert_not_called()
    mock_command.assert_called_once_with("1",
                                         "2",
                                         original_msg=msg3.message,
                                         alias_used="a_command",
                                         quiet_action=True)

    post_msg.reset_mock()
    mock_command.reset_mock()

    msg3.message.content = "!!/a_command 3"
    chatcommunicate.on_msg(msg3, client)

    assert post_msg.call_count == 1
    assert post_msg.call_args_list[0][0][0][1] == ":999 hi"
    mock_command.assert_called_once_with("3",
                                         None,
                                         original_msg=msg3.message,
                                         alias_used="a_command",
                                         quiet_action=False)

    post_msg.reset_mock()
    mock_command.reset_mock()

    msg4 = Fake(
        {
            "message": {
                "room": {
                    "id": 11540,
                },
                "owner": {
                    "id": 1
                },
                "parent": {
                    "owner": {
                        "id": 2
                    }
                },
                "id": 1000,
                "content": "asdf"
            }
        },
        spec=chatcommunicate.events.MessageEdited)

    chatcommunicate.on_msg(msg4, client)

    msg5 = Fake(
        {
            "message": {
                "room": {
                    "id": 11540,
                },
                "owner": {
                    "id": 1
                },
                "parent": {
                    "owner": {
                        "id": 1337
                    }
                },
                "id": 1000,
                "content": "@SmokeDetector why   "
            }
        },
        spec=chatcommunicate.events.MessageEdited)

    chatcommunicate._reply_commands["why"] = (mock_command, (0, 0))

    threw_exception = False

    try:
        chatcommunicate.on_msg(msg5, client)
    except AssertionError:
        threw_exception = True

    assert threw_exception
    mock_command.assert_not_called()
    post_msg.assert_not_called()

    chatcommunicate._reply_commands["why"] = (mock_command, (1, 1))
    chatcommunicate.on_msg(msg5, client)

    assert post_msg.call_count == 1
    assert post_msg.call_args_list[0][0][0][1] == ":1000 hi"
    mock_command.assert_called_once_with(msg5.message.parent,
                                         original_msg=msg5.message,
                                         alias_used="why",
                                         quiet_action=False)

    post_msg.reset_mock()
    mock_command.reset_mock()

    msg5.message.content = "@SmokeDetector why@!@#-"
    chatcommunicate.on_msg(msg5, client)

    post_msg.assert_not_called()
    mock_command.assert_called_once_with(msg5.message.parent,
                                         original_msg=msg5.message,
                                         alias_used="why",
                                         quiet_action=True)

    msg6 = Fake(
        {
            "message": {
                "room": {
                    "id": 11540,
                },
                "owner": {
                    "id": 1
                },
                "id": 1000,
                "parent": None,
                "content": "sd why - 2why 2why- 2- why- "
            }
        },
        spec=chatcommunicate.events.MessageEdited)

    get_last_messages.side_effect = lambda _, num: (Fake({"id": i})
                                                    for i in range(num))
    chatcommunicate.on_msg(msg6, client)

    assert post_msg.call_count == 1
    assert post_msg.call_args_list[0][0][0][
        1] == ":1000 [:0] hi\n[:1] <skipped>\n[:2] hi\n[:3] hi\n[:4] <processed without return value>\n[:5] <processed without return value>\n[:6] <skipped>\n[:7] <skipped>\n[:8] <processed without return value>"