Compare commits

...

9 Commits

Author SHA1 Message Date
iRaven
ae8c8c7b90 minor updates to gifcombine 2022-11-23 20:58:07 -06:00
iRaven
2487310eb1 new thingy feature: gif combiner! ~yay~
this took me too much time because fuck indenting and iterations
2022-11-23 04:11:25 -06:00
iRaven
e4221baf7e archiving transtar cameras
trans rights are always human rights
2022-11-21 15:15:39 -06:00
iRaven
0b06939718
obvious change here not to include archive data 2022-11-15 09:42:08 -06:00
iRaven
029efbccab
giving arg info 2022-11-14 01:03:37 -06:00
iRaven
ba154b324a new method to pull file content, using requests module only
faster
2022-11-01 15:33:22 -05:00
iRaven
cdb303825d fixing standalone run, disabling unnecessary logs from urllib3, 2022-09-28 03:38:29 -05:00
iRaven
e4f0d705c6
Update README.md 2022-09-08 04:20:16 -05:00
iRaven
ccec7d8416 adding argument functionality for looping the main app with a script 2022-09-08 04:08:09 -05:00
5 changed files with 254 additions and 17 deletions

12
.gitignore vendored
View File

@ -1,3 +1,13 @@
CCTVCrawl*
devscrape*
*.log*
OLD_devscrape*
*.log
TransArchive*.csv
# ide/py cache/settings files
__pycache__/
.vscode/
# do not sync archive feeds prod folder
archive/

View File

@ -1,2 +1,20 @@
# TranstarArchive
Python application intended to store an archive of live camera feeds from Houston Transtar
## requirements
python 3.6 or later
the requests and wget Python modules, installed with pip (if others aren't found on your system, they can be easily viewed in the source code c:)
## what does this program do?
retrives images from live and valid camera image feeds from Houston Transtar. normally these can be viewed on their website [here](https://traffic.houstontranstar.org/cctv/transtar/), or a very very lightweight version (intended for mobile or older devices, that i prefer) can be found [here](http://traffic.houstontranstar.org/mobile/transtar_cctv.aspx), stores them in a folder/local archive on the system you run it on
## why?
i have no idea
## arguments
by default and with no args provided TranstarArchive will create required folders if necessary and bring you to the main menu. this is useful for archiving once, however below can be more useful if you want to continuously archive.
-archive will start archiving feeds with no extra prompts. use a looping script provided (for windows as of 9/8/22) to continuously loop the process.
-testarg is self explanatory. tests if TranstarArchive will accept arguments

13
TranstarArchive_Loop.bat Normal file
View File

@ -0,0 +1,13 @@
@echo off
title TranstarArchive Looping Test (for Windows)
echo %cd%
set /p confirm=This will create a loop for archiving files from transtar, delayed every few minutes, are you sure?
if %confirm% == yes goto loop
if %confirm% == no goto :eof
goto :eof
:loop
echo Starting to loop @ %date% %time%
python.exe %cd%\main.py -archive
timeout 17
goto loop

165
gifcombine.py Normal file
View File

@ -0,0 +1,165 @@
import imageio
import os
import sys
import logging
import time
# TranstarArchive Image GIF Combine PY
# author: iRaven (https://iravenhome.net)
# Started 11/22/22.
# version="2022.11.22"
# Configure logging
logging.basicConfig(filename="TranstarArchive_gifCombine.log",
format='%(asctime)s %(levelname)s %(message)s',
filemode='a')
log = logging.getLogger()
# log.setLevel(logging.DEBUG) # use this for debugging
log.setLevel(logging.INFO) # use this for production
arglist = sys.argv[1:]
#time -- if this will ever be used? logging takes care of this
initcurtime = time.localtime()
curtime = time.strftime("%H-%M-%S", initcurtime)
curdate = (f'{initcurtime.tm_year}-{initcurtime.tm_mon}-{initcurtime.tm_mday}')
global imagespath
global dateinput
# valid feeds list to iterate thru
# TODO: make this user supplied for older folders maybe
vftxt = open("valid_feed_list.txt", "r")
vfdata = vftxt.read()
vfeeds = vfdata.split("\n")
vftxt.close()
def initgifFolder(path, date): # makes sure gif folder exists for date provided in a certain path
if not os.path.exists(f'{path}/{date}/gifs'):
log.warning(f"gifs folder in {path}/{date} does not exist, creating it")
os.makedirs(f"{path}/{date}/gifs")
else:
log.info(f"gifs folder in {path}/{date} exists, ignoring check")
def gifCombine(path, date):
# images=[]
initgifFolder(path,date) # make sure gif folder exists for date provided
joinedpath = os.path.join(path, date)
# print(joinedpath) # debugging- comment this out on prod !!!
for feednum in vfeeds:
images=[] # list of images found to append to output gif image for each feednum (resets with nothing for each feednum)
imagenames=[]
for filenames in sorted(os.listdir(joinedpath)): # for each file in provided path dir
if filenames.startswith(feednum): # if a file starts with the current feednum
# length check!! (this bit me in the ass)
# print(len(filenames.split('_')[0])) # debugging
if len(filenames.split('_')[0]) == len(feednum):
log.info(f"found {filenames} that starts with {feednum}")
print(f"found {filenames} that starts with {feednum}")
if filenames in imagenames: # fsakdjfjaksldfjklasdfjklakljdsxf holy shit so many checks! see if a file name has already been added to list for gif
log.debug(f'found {filenames} already in {feednum} filename list so NOT adding to list AGAIN')
else:
# log.info("") # not sure what i was doing here
#if os.path.isfile(f'{joinedpath}/gifs/{feednum}.gif'): # check if a file exists so we don't waste time with imageio reading contents
# (TODO: may improve if ran earlier and new feeds are added?) (this is that LOL) (nope this doesn't really work)
# log.info(f"gif file for {feednum} already exists at \'{joinedpath}/gifs/{feednum}.gif\', not creating again and moving on...")
# print(f"gif file for {feednum} already exists at \'{joinedpath}/gifs/{feednum}.gif\', not creating again and moving on...")
#else:
imagenames.append(filenames) # append found file names to list for adding to imageio reader appending list
else:
log.debug(f'found {filenames} that starts with {feednum} HOWEVER isn\'t right length')
else:
log.debug(f"{filenames} does not start with {feednum}")
for files in imagenames:
log.info(f"applying image {files} for {feednum} in {joinedpath}")
print(f"applying image {files} for {feednum} in {joinedpath}")
try:
images.append(imageio.imread(f'{joinedpath}/{files}')) # append whatever image found that starts with current feednum to list
#TODO: this gives a deprecated error about imread because of course it does.
except ValueError:
log.debug(f"a corrupted file has been detected! {images}")
log.error(f"a ValueError has occured on {feednum}, maybe due to a corrupted .jpg file that may have been appended.")
log.error(f"{feednum} ValueError: {joinedpath}/gifs/{feednum}.gif will not be created and ignored.")
images.remove(files) # maybe this will remove only the file that got fucked up?
# log.debug(f"all images found to be saved: \n{images}") -- this generates way too much bullshit
log.debug(f" all images to be saved in a gif: \n{imagenames}")
log.info(f"saving {feednum} gif file with all images collected of it on {date}...")
print(f"saving {feednum} gif file with all images collected of it on {date}...")
log.debug(f"checking if gif for {feednum} already exists")
if os.path.isfile(f'{joinedpath}/gifs/{feednum}.gif'): # check if a file exists so we don't create it again (TODO: may improve if ran earlier and new feeds are added?)
log.info(f"gif file for {feednum} already exists at \'{joinedpath}/gifs/{feednum}.gif\', not creating again and moving on...")
else: # if file doesn't exist already, make it
imageio.mimsave(f'{joinedpath}/gifs/{feednum}.gif', images, duration=0.2) # save a gif image for each feednum in date folder provided with .2 secs between each frame
log.info("gif should be saved and created successfully. moving on to next itieration...")
print("gif should be saved and created successfully. moving on to next itieration...")
def MainMenu():
log.info("main menu started")
print("TranstarArchive gifCombine App")
print("this program will combine any feed images archived by TranstarArchive for a specific date you provide")
# print(" ")
print(" ") # line breaks? LOL
print("first, let's start off with a path where all your images are stored, which must contain specific date folders.")
print("normally this path is in the folder you ran this script in, /archive.")
log.debug("prompting user for path selection choice, default or custom")
menuin1 = input("please type Y if this is correct or N to enter a different folder path: ")
menuin1 = menuin1.lower()
if menuin1 == "y":
imagespath = "./archive"
log.info("images path was set to default /archive folder")
elif menuin1 == "n":
log.debug("user chose to enter a custom path to be scanned")
menuin2 = input("please type a custom path here for gifCombine to scan: ")
log.debug(f"user inputted {menuin2}, now checking if this path is actually a thing")
if os.path.exists(menuin2):
imagespath = menuin2
log.info(f"user inputted path {menuin2} EXISTS, going on...")
else:
log.error(f"user inputted path {menuin2} DOES NOT EXIST, trying again...")
print(f"the path you entered ({menuin2} couldn't be found, please try that again!")
MainMenu() # this feels incredibly chaotic, a function calling itself LOL
# exit() # ^ if that doesn't work or breaks things tremendously, fuck it
else:
exit() # fuck it if that selection wasn't y or n. not sure what to do, i'll improve this later (2022/11/22)
# TODO: valid_feeds_list file input
print(" ") # line breaks? LOL
log.debug("prompting user for date selection choice")
print("second, you'll need to choose which date do you want to combine gifs for. ")
log.debug(f"getting dir listing of {imagespath} for date selection")
print("here is a listing of the directories in the path you provided earlier.")
print(os.listdir(imagespath))
menuin3 = input("type in the folder with the date you want gifCombine to iterate through: ")
# TODO: formatting error correction
dateinput = menuin3 # just declare it here
print(" ") # line breaks? LOL
log.debug("prompting user for confirmation")
log.info(f"final options before confirmation: path={imagespath}, date={dateinput}")
print(f"before we start, you have chosen your file path as {imagespath} and the date to work through {dateinput}")
print("this may take a while depending on how many images are to be processed.")
menuin4 = input("type in \"startrans\" to continue and start processing: ")
if menuin4 == "startrans":
# go!
print("making sure folders are set up...")
initgifFolder(imagespath, dateinput) # make gifs folder in specced dir
print("preparing for epic sonic rainboom...")
print("now starting to gif combine!")
gifCombine(imagespath, dateinput) # go bitch
exit() # exit when done
else:
exit() # fuck off
# arguments
# TODO: wait fuck that's not really a good idea rn lol
# start program
log.info("TranstarArchive's gifCombine was STARTED!")
MainMenu()

63
main.py
View File

@ -2,27 +2,29 @@ import logging
import os
import wget
import time
import datetime
import sys
import requests
import csv
import threading
# TranstarArchive Main PY
# author: iRaven (https://iravenhome.net)
# Started 9/6/22.
#version = "0.1"
#version = "2022.9.28"
# Configure logging
logging.basicConfig(filename="TransArchive.log",
format='%(asctime)s %(message)s',
logging.basicConfig(filename="TranstarArchive.log",
format='%(asctime)s %(levelname)s %(message)s',
filemode='a')
log = logging.getLogger()
log.setLevel(logging.DEBUG)
logging.getLogger("requests").setLevel(logging.WARNING)
logging.getLogger("urllib3").setLevel(logging.WARNING)
#define local vars
arglist = sys.argv[1:]
#time
initcurtime = time.localtime()
# currtime = (f'{initcurtime.tm_hour}-{initcurtime.tm_min}-{initcurtime.tm_sec}')
@ -33,7 +35,7 @@ csvfile = (f"TransArchive_{curdate}.csv") # mainly for debugging but to show sta
csvfields = ['time','camera_id', 'status'] # ^
# very important var: where we get everything
cctvurl = (f'https://www.houstontranstar.org/snapshots/cctv/') # Last updated Sep-2022
cctvurl = (f'https://www.houstontranstar.org/snapshots/cctv/') # Last updated Sep-6-2022
# very important var: list of valid camera feeds generated by devs (likely included and updated in repo)
vftxt = open("valid_feed_list.txt", "r")
vfdata = vftxt.read()
@ -45,8 +47,12 @@ vftxt.close()
######## Core functions
# initialize folder
def initFolder():
log.info(f'TranstarArchive was started')
def initFolder(startmode):
if startmode == "script":
log.info(f'TranstarArchive was likely started non-standalone with a script or from a command line')
else:
log.info(f'TranstarArchive was started')
if not os.path.exists("archive/"):
log.info("archive folder doesn't exist. creating it")
os.makedirs("archive/")
@ -54,7 +60,7 @@ def initFolder():
log.warning("archive folder for todays date doesn't exist (expected LOL), creating it")
os.makedirs(f"archive/{curdate}")
elif not os.path.exists(f"TransstarArchive_{curdate}.csv"):
log.error("csv file doesn't exist. creating it for today")
log.warning("csv file doesn't exist. creating it for today")
with open(csvfile, 'a') as listfile:
csvwrite = csv.writer(listfile)
csvwrite.writerow(csvfields)
@ -73,7 +79,9 @@ def imageDownload(url):
csvvalid = [curtime,feed,'Success']
print(f'Valid camera feed is being archived: {feed}\n')
log.info(f'Valid camera feed is being archived: {feed}')
wget.download(rq.url,f'archive/{curdate}/{feed}_{curtime}.jpg')
# wget.download(rq.url,f'archive/{curdate}/{feed}_{curtime}.jpg')
# new method - using requests module only (10.20.22)
open(f'archive/{curdate}/{feed}_{curtime}.jpg', 'wb').write(rq.content) # ^
with open(csvfile, 'a') as listfile:
csvwrite = csv.writer(listfile)
csvwrite.writerow(csvvalid)
@ -86,7 +94,7 @@ def imageDownload(url):
# for vals in invlog:
# invlog.write(f'invalid feeds found at archive {curdate} at {curtime}:\n{vals}\n#### END END END ####\n either transstar is having issues or has reconfigured feed numbers, open an issue in the repo: https://github.com/iraven4522/TranstarArchive\n')
# loops the download function every like 3 or so mins
# loops the download function every like 3 or so mins (may not work?)
def imgDownloadLoop(secs):
log.info(f'delay loop was called for {secs}, starting now')
threading.Timer(f'{secs}.0', imgDownloadLoop).start()
@ -106,13 +114,36 @@ def MainMenu():
menuin1 = input("If you want to continue please type the phrase \"startrans\" (without quotes) or type no: ")
if menuin1 == "startrans":
imageDownload(cctvurl)
log.info("returned to menu for delay")
imgDownloadLoop(195)
# log.info("returned to menu for delay")
# imgDownloadLoop(195)
else:
exit()
else:
exit()
# Run the shit (finally)
initFolder() # check folder and csv file first (send log start message)
MainMenu()
# Run the shit (finally) -- phased out due to arguments
# initFolder() # check folder and csv file first (send log start message)
# MainMenu()
# Arguments
for arg in arglist:
# print(arglist)
if arg in ("-archive"):
# print("Archive was passed") # debugging
initFolder("script")
imageDownload(cctvurl)
elif arg in ("-testarg"): # debugging, left to test arguments
print("test arg was passed")
log.debug("Test arg was passed -- not running")
else: # unrecognized arguments are passed (which is oki)
# log.debug("no args were passed!")
# log.debug("unrecognized args were passed!")
initFolder("normal")
MainMenu()
# noticed an issue where this doesn't run standalone anymore. maybe this will fix it. idk
if len(arglist) == 0:
# log.debug("no args were passed!")
initFolder("noarg")
MainMenu()
# 09/28/22- ok this will semi work for now. if any arg other than the ones defined above are passed it'll ignore them and run like none were passed