Python watch QNAP FTP directory for changes and send UDP messages

215 Views Asked by At

I need to write a program that watches a directory on ftp server and then sends a message with the path to the new file. So I did manage to use watchdog for a local folder with this as I need just the create event:

if __name__ == "__main__":
    patterns = "*"
    ignore_patterns = ""
    ignore_directories = False
    case_sensitive = False
    my_event_handler = PatternMatchingEventHandler(patterns, ignore_patterns, ignore_directories, case_sensitive)

    def on_created(event):
        byte_message = bytes(f"{event.src_path}", "utf-8")
        opened_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        opened_socket.sendto(byte_message, ('address', port))
        print(f"{event.src_path} created")
    
    my_event_handler.on_created = on_created

    path = r"local/path"
    go_recursively = True
    my_observer = Observer()
    my_observer.schedule(my_event_handler, path, recursive=go_recursively)

    my_observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        my_observer.stop()

But when I try replacing the path with the folder on that FTP I get Access Denied which is correct as I did't set the login and the password. After that I did this, based on an answer on Stack Overflow:

ftp = FTP()
ftp.set_pasv(True)
ftp.connect("address")
ftp.login('user', 'pass')

def changemon(dir='ftp/path/*'):
    ls_prev = set()

    while True:
        ls = set(ftp.nlst(dir))

        add = ls-ls_prev
        if add: 
            yield add 
        ls_prev = ls
        sleep(5)

for add in changemon():
    byte_message = bytes('\n'.join(r'address%' % i for i in add), 'utf-8')
    opened_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    opened_socket.sendto(byte_message, ('address', port))

The problem with this is that it gets every single file that appears in the dir.

So I need something that I can extract the subfolder names and file names from. Like this: file1 and file2 are newly created:

ftp/path/5000/file1
ftp/path/5001/file2

print('Folder is: ' + foldername)
Folder is: 5000
Folder is: 5001
print('New file is: ' + filename)
New file is: file1
New file is: file2

Any help is welcome.

1

There are 1 best solutions below

0
On BEST ANSWER

This is the working solution after me not able to find anything that could help me from the store (and the task was to make it in python):

from ftplib import FTP
from time import sleep
import os
import byte
import socket
import numpy as np
import pandas as pd

ftp = FTP()
ftp.set_pasv(True)
ftp.connect("some-ip-address")
ftp.login('user', 'password')

def changemon(dir='/dir/*'):
    ls_prev = set()

    while True:
        ls = set(ftp.nlst(dir))

        add = ls-ls_prev
        if add:
            yield add

        ls_prev = ls
        sleep(5)

#tcp
for add in changemon():
    result = [i for i in add]
    array = np.array(result, dtype='str')
    df = pd.DataFrame(array, columns=None, index=None)
    for a in array:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((host, port))
        name = a.split('/')
        separator = ''
        path = (r'ip\dir\\' + str(name[2]) + '\\' + str(name[3]))
        device = name[2]
        message = bytes(separator.join(f'{device} desired string for the IP notification  \n'), 'utf-8')
        s.send(message)
        sleep(5)

It's not the prettiest solution, but gets the job done. The slashes are in the oposite direction because the message needs to be read in Windows. The path variable is then inserted in a database.