Python Forum
Matching multiple parts in string
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Matching multiple parts in string
#21
The ! is a logical NOT

re docs:

Quote:(?=...)
Matches if ... matches next, but doesn’t consume any of the string. This is called a lookahead assertion. For example, Isaac (?=Asimov) will match 'Isaac ' only if it’s followed by 'Asimov'.

(?!...)
Matches if ... doesn’t match next. This is a negative lookahead assertion. For example, Isaac (?!Asimov) will match 'Isaac ' only if it’s not followed by 'Asimov'.

fnmatch was conceived as a Unix file name matcher. Maybe better to stick with re.
Reply
#22
The hosts are added line by line among each other by a eggdrop (TCLbot) in the userlist.txt, thats why the exclamation mark, my python script must read this userlist.txt, the script i posted before is working, even with the *!* added in the line in userlist.txt with:
if any(host in u for u in users):
That works,
only if the hosts in the userlist.txt are full added like:
*!*@vmi2234.contaboserver.net
If the host is added like:
*!*@*.contaboserver.net in userlist.txt
it doesn't work anymore.
I even added manually hosts in the userlist.txt without *!*@, e.g.:
*.contaboserver.net
Without any results.
I need python to read the userlist.txt to match the host that joins the irc channel, even with *&^%$#@ etc. characters added in the line in userlist.txt
Reply
#23
(Jun-07-2022, 11:42 PM)fozz Wrote: I even added manually hosts in the userlist.txt without *!*@, e.g.:
*.contaboserver.net
Without any results.
You cannot just randomly change the pattern without analyzing why it doesn't work in detail.
fozz Wrote:I need python to read the userlist.txt to match the host that joins the irc channel
Python executes faithfully the statements that you give it to execute, that's all it can do.
Reply
#24
(Jun-07-2022, 09:38 PM)Pedroski55 Wrote: The ! is a logical NOT

Yes, but only in square-brackets: https://docs.python.org/3/library/fnmatch.html


The format of this ident:
nickname!~username@host

The ~ is used, if the user has no ident server running.
The ! splits the nickname and username.


Example:
import fnmatch

pattern = "*!*@vmi2234.contaboserver.net"

users = [
    "[email protected]", # me with an Ident server
    "[email protected]", # no ident server, ~
    "[email protected]", # no ident server and different host
]


for user in users:
    if fnmatch.fnmatch(user, pattern):
        print("[✓]", end=" ")
    else:
        print("[⚠]", end=" ")

    print(user)
Output:
[✓] [email protected] [✓] [email protected] [⚠] [email protected]
If you're reading from a file, the line ending is not removed. So fnmatch could not find a match.
Maybe this is the cause why you don't get any match.

# userlist.txt, each line one user
# patternlist.txt, each pattern one line

from fnmatch import fnmatch
# this time the fnmatch is the fnmatch function from fnmatch module
# so in code fnmatch() must be used instead of fnmatch.fnmatch()


def user_match(user, patterns):
    """
    Return True, if user matches to one of the given patterns
    otherwise, False is returned
    """
    return any(fnmatch(user, pattern) for pattern in patterns)


with open("patterns.txt") as fd:
    patterns = list(map(str.rstrip, fd))
    # all whitespaces on the right side are stripped

with open("userlist.txt") as fd:
    userlist = list(map(str.rstrip, fd))


for user in userlist:
    if user_match(user, patterns):
        print("[✓]", end=" ")
    else:
        print("[⚠]", end=" ")
    print(user)
userlist.txt
[email protected]
[email protected]
[email protected]
patterns.txt
*!*@vmi2234.contaboserver.net
*!*@irc.libra.chat
Output:
[✓] [email protected] [✓] [email protected] [✓] [email protected]
If I remove irc.libra.chat:
Output:
[✓] [email protected] [✓] [email protected] [⚠] [email protected]
Gribouillis likes this post
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#25
I appreciate the help, thanks again.

This is not solving my problem, i think you folks reading over the problem/situation.
I'm gonna explain this for the last time, otherwise I'll give up.

My irc client can run python scripts,
when a user joins the irc server/channel with:

[email protected]

The phyton script checks the address from the user who joined the irc channel and if the above string matches a line in my userlist.txt
(where a line is added like):

*!*@*.contaboserver.net

it should match, so further action can be taken by the script, and please any help how to implement it in the existing script i posted, thats all.
Thanks in advance, fozz
Reply
#26
But your example does match:

In [1]: import fnmatch

In [2]: fnmatch.fnmatch("[email protected]", "*!*@*.contaboserver.net")
Out[2]: True
Provide us with a userlist.txt (you can anonymize it), the patterns (one or more?) and the code which fails.
Did you recognize that newline characters are not filtered out? This fact is important, if you're reading a file.
Not stripping the right side of the string, will give a False negative results.

Here, the \n is added to the str.
In [3]: fnmatch.fnmatch("[email protected]\n", "*!*@*.contaboserver.net")
Out[3]: False
Using the method rstrip on a str will strip all white spaces from the right side, until a NON-Whitespace character is reached.
Which Characters are whitespace, is defined in string.whitespace. The newline character is also seen as a whitespace, when using strip/rstrip.
In [4]: fnmatch.fnmatch("[email protected]\n".strip(), "*!*@*.contaboserver.net")
Out[4]: True
Here, the rstrip just removes the newline character \n.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#27
Thank you, I already pasted the code with explanation's and the part that doesn't work before in this topic, I realy dont know how to stress this situation more out, the userlist hosted in my /home/folder is like:
*!*@*.t-ipconnect.de
*!*@91.205.72.*
*!*@*.versanet.de
*!*@*.net-htp.de
*!*@*.vodafone-ip.de
*!*@91.136.195.*
*!*@*.vps.ovh.net
*!*@*.contaboserver.net
*!*@*.your-server.de
*!*@88.79.151.*
*!*@mercury.agencia.mk
*!*@92.119.90.*
*!*@173.249.33.*
*!*@212.227.* 
*!*@*.as20676.net
*!*@*.telefonica.de
*!*@83.236.16.*
*!*@91.246.194.*
*!*@webchat.*.net
When a user joins my irc channel and that host matches with one added in my userlist.txt it should reconize it, in the posts before i told i've got the next code:
if any(host in u for u in users):
BUT that is only working when the address/host is added in the userlist.txt like :

*!*@vmi2234.contaboserver.net
or
*!*@webchat.ircnet.net

Insteed of

*!*@*.contaboserver.net
or
*!*@webchat.*.net

added in the userlist.txt

The userlist.txt is added with the wildcarded addresses line under line. Don't know how to explain this more precisely.
Reply
#28
The way, how the weechat API works, is messed up. I never used this api before,
I tested this code together with weechat and I get operator status (using libra irc webchat for second user).

from __future__ import annotations

import time
from fnmatch import fnmatch
from pathlib import Path

import weechat

# get the directory where the script is running
APPDIR = Path(__file__).absolute().parent

# userlist.txt should be next to script (same directory)
USER_FILE = APPDIR / "userlist.txt"

# max age of cache in secods
MAX_CACHE_AGE = 5 * 60

# dict to cache the userlist entries
cache : dict = {"age": None, "userlist": []}


def get_user_list() -> list[str]:
    """
    Retrieve cached userlist from userlist.txt
    If the age is older than 5 minutes, the cache is refreshed.
    """

    def read() -> list[str]:
        """
        Read the userlist.txt and return the lines stripped in a list
        """
        with USER_FILE.open() as fd:
            return [user for user in map(str.strip, fd) if user]

    if cache["age"] is None or not cache["userlist"] or cache["age"] > time.time():
        cache["userlist"] = read()
        cache["age"] = time.time() + MAX_CACHE_AGE

    return cache["userlist"]


def is_op(user: str) -> bool:
    """
    Checking user against each line of userlist.txt for a match.
    The userlist is take from get_user_list(), which caches
    the content for 5 minutes. Then the file is read again.
    """
    return any(fnmatch(user, pattern) for pattern in get_user_list())


def user_join_callback(data, signal, signal_data):
    network = signal.split(",", maxsplit=1)[0]
    address = signal_data.split(maxsplit=1)[0].removeprefix(":")
    nick = address.split("!", maxsplit=1)[0]

    msg = weechat.info_get_hashtable("irc_message_parse", {"message": signal_data})
    buffer = weechat.info_get("irc_buffer", f"{network},{msg['channel']}")

    if is_op(address):
        weechat.prnt("", f"User {address} is recognized as OP")
        weechat.command(buffer, f"/wait 1 /mode {CHANNEL} +o {nick}")
    else:
        weechat.prnt("", f"User {address} is not an OP")

    return weechat.WEECHAT_RC_OK


CHANNEL = "#python-test"
weechat.register("op_script", "DeaD_EyE", "0.0.1", "BSD-0", "Auto OP script", "", "")
weechat.hook_signal("*,irc_in2_join", "user_join_callback", "")
Quote:→ testpythondeadey has joined
ⓘ Guest7021 gives ops to testpythondeadey

Guest7021 is the weechat + script. testpythondeadey was the irc web client.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#29
DeaD_EyE: you are the bomb, THANK YOU,
This is where im looking for, clear explanation also :)
I tested the script and works very well, the only side note is:
I'm on multiple networks and the script triggers on all networks ive joined , how can I specify to do the job only for one particulair network and channel?
The message i get in the status window for other networks (where im not opped or joined the specified channel) is:
nickname #somechannel: They aren't on that channel
and
#somechannel: You're not a channel operator
Is this easy to fix?
I'm happy with your code, thanks a lot!
Reply
#30
Got it all working now, thanks again for all the help!

Greetings, fozz
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Matching string from a file tester_V 5 468 Mar-05-2024, 05:46 AM
Last Post: Danishhafeez
  splitting file into multiple files by searching for string AlphaInc 2 917 Jul-01-2023, 10:35 PM
Last Post: Pedroski55
  Save multiple Parts of Bytearray to File ? lastyle 1 969 Dec-10-2022, 08:09 AM
Last Post: Gribouillis
  matching a repeating string Skaperen 2 1,275 Jun-23-2022, 10:34 PM
Last Post: Skaperen
  Extract parts of multiple log-files and put it in a dataframe hasiro 4 2,107 Apr-27-2022, 12:44 PM
Last Post: hasiro
  Search multiple CSV files for a string or strings cubangt 7 8,111 Feb-23-2022, 12:53 AM
Last Post: Pedroski55
  Matching Exact String(s) Extra 4 1,954 Jan-12-2022, 04:06 PM
Last Post: Extra
  Replace String in multiple text-files [SOLVED] AlphaInc 5 8,194 Aug-08-2021, 04:59 PM
Last Post: Axel_Erfurt
Question How to extract multiple text from a string? chatguy 2 2,403 Feb-28-2021, 07:39 AM
Last Post: bowlofred
  How to print string multiple times on new line ace19887 7 5,799 Sep-30-2020, 02:53 PM
Last Post: buran

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020