#!/usr/bin/env python3"""Script to upload images to Wikipedia.The following parameters are supported:-keep Keep the filename as is-filename: [str] Target filename without the namespace prefix-prefix: [str] Add specified prefix to every filename.-noverify Do not ask for verification of the upload description if one is given-abortonwarn: Abort upload on the specified warning type. If no warning type is specified, aborts on any warning.-ignorewarn: Ignores specified upload warnings. If no warning type is specified, ignores all warnings. Use with caution-chunked: Upload the file in chunks (more overhead, but restartable). If no value is specified the chunk size is 1 MiB. The value must be a number which can be preceded by a suffix. The units are:: No suffix: Bytes 'k': Kilobytes (1000 B) 'M': Megabytes (1000000 B) 'Ki': Kibibytes (1024 B) 'Mi': Mebibytes (1024x1024 B) The suffixes are case insensitive.-async Make potentially large file operations asynchronous on the server side when possible.-always Don't ask the user anything. This will imply -keep and ``-noverify`` and require that either ``-abortonwarn`` or ``-ignorewarn`` is defined for all. It will also require a valid file name and description. It'll only overwrite files if ``-ignorewarn`` includes the 'exists' warning.-recursive When the filename is a directory it also uploads the files from the subdirectories.-summary: [str] Pick a custom edit summary for the bot.-descfile: [str] Specify a filename where the description is storedIt is possible to combine ``-abortonwarn`` and ``-ignorewarn`` so thatif the specific warning is given it won't apply the general one but morespecific one. So if it should ignore specific warnings and abort on therest it's possible by defining no warning for -abortonwarn and thespecific warnings for ``-ignorewarn``. The order does not matter. Ifboth are unspecific or a warning is specified by both, it'll preferaborting.If any other arguments are given, the first is either URL, filename ordirectory to upload, and the rest is a proposed description to go withthe upload. If none of these are given, the user is asked for thedirectory, file or URL to upload. The bot will then upload the image tothe wiki.The script will ask for the location of an image(s), if not given as aparameter, and for a description."""## (C) Pywikibot team, 2003-2024## Distributed under the terms of the MIT license.#from__future__importannotationsimportcodecsimportmathimportosimportreimportpywikibotfrompywikibot.botimportsuggest_helpfrompywikibot.specialbotsimportUploadRobotCHUNK_SIZE_REGEX=re.compile(r'-chunked(?::(\d+(?:\.\d+)?)[ \t]*(k|ki|m|mi)?b?)?',re.IGNORECASE)
[docs]defget_chunk_size(match)->int:"""Get chunk size."""ifnotmatch:pywikibot.error('Chunk size parameter is not valid.')chunk_size=0elifmatch[1]:# number was in therebase=float(match[1])ifmatch[2]:# suffix toosuffix=match[2].lower()ifsuffix=='k':suffix=1000elifsuffix=='m':suffix=1000000elifsuffix=='ki':suffix=1<<10elifsuffix=='mi':suffix=1<<20else:suffix=1chunk_size=math.trunc(base*suffix)else:chunk_size=1<<20# default to 1 MiBreturnchunk_size
[docs]defmain(*args:str)->None:"""Process command line arguments and invoke bot. If args is an empty list, sys.argv is used. :param args: command line arguments """url=''description=[]summary=Nonekeep_filename=Falsealways=Falseuse_filename=Nonefilename_prefix=Noneverify_description=Trueaborts=set()ignorewarn=set()chunk_size=0asynchronous=Falserecursive=Falsedescription_file=None# process all global bot args# returns a list of non-global args, i.e. args for upload.pylocal_args=pywikibot.handle_args(args)foroptioninlocal_args:arg,_,value=option.partition(':')ifarg=='-always':keep_filename=Truealways=Trueverify_description=Falseelifarg=='-recursive':recursive=Trueelifarg=='-keep':keep_filename=Trueelifarg=='-filename':use_filename=valueelifarg=='-prefix':filename_prefix=valueelifarg=='-summary':summary=valueelifarg=='-noverify':verify_description=Falseelifarg=='-abortonwarn':ifvalueandabortsisnotTrue:aborts.add(value)else:aborts=Trueelifarg=='-ignorewarn':ifvalueandignorewarnisnotTrue:ignorewarn.add(value)else:ignorewarn=Trueelifarg=='-chunked':match=CHUNK_SIZE_REGEX.fullmatch(option)chunk_size=get_chunk_size(match)elifarg=='-async':asynchronous=Trueelifarg=='-descfile':description_file=valueelifnoturl:url=optionelse:description.append(option)description=' '.join(description)ifdescription_file:ifdescription:pywikibot.error('Both a description and a -descfile were ''provided. Please specify only one of those.')returnwithcodecs.open(description_file,encoding=pywikibot.config.textfile_encoding)asf:description=f.read().replace('\r\n','\n')whilenot('://'inurloros.path.exists(url)):ifnoturl:error='No input filename given.'else:error='Invalid input filename given.'ifnotalways:error+=' Try again.'ifalways:url=Nonebreakpywikibot.info(error)url=pywikibot.input('URL, file or directory where files are now:')ifalwaysand(abortsisnotTrueandignorewarnisnotTrueornotdescriptionorurlisNone):additional=''missing=[]ifurlisNone:missing.append('filename')additional=error+' 'ifdescriptionisNone:missing.append('description')ifabortsisnotTrueandignorewarnisnotTrue:additional+=('Either -ignorewarn or -abortonwarn must be ''defined for all codes. ')additional+='Unable to run in -always mode'suggest_help(missing_parameters=missing,additional_text=additional)returnifos.path.isdir(url):file_list=[]fordirectory_infoinos.walk(url):ifnotrecursive:# Do not visit any subdirectoriesdirectory_info[1][:]=[]fordir_fileindirectory_info[2]:file_list.append(os.path.join(directory_info[0],dir_file))url=file_listelse:url=[url]bot=UploadRobot(url,description=description,use_filename=use_filename,keep_filename=keep_filename,verify_description=verify_description,aborts=aborts,ignore_warning=ignorewarn,chunk_size=chunk_size,asynchronous=asynchronous,always=always,summary=summary,filename_prefix=filename_prefix)bot.run()