1618 lines
48 KiB
Python
1618 lines
48 KiB
Python
# -*- coding: utf-8 -*-
|
|
#@Name FromDucks
|
|
#@Hook Books
|
|
#@Image fromducks.png
|
|
#@Key FromDucks
|
|
#@Description Search on coa.inducks.org informations about the selected eComics
|
|
#
|
|
# FromDucks 2.15 - Jun 2022
|
|
#
|
|
# ---> 2.15 Changelog: Fixed bugs found by /u/MxFlix. Packaged by /u/quinyd
|
|
#
|
|
# FromDucks 2.14 - Jul 2018
|
|
#
|
|
# ---> 2.14 Changelog: fixed other bugs
|
|
#
|
|
# You are free to modify, enhance (possibly) and distribute this file, but only if mentioning the (c) part
|
|
#
|
|
# (C)2007-2013 cYo Soft & (C)2008 DouglasBubbletrousers & (C)2008 wadegiles & (C)2010 cbanack
|
|
# (C)2009-2010 oraclexview aka SoundWave
|
|
#
|
|
# Data (C) The Inducks Team (http://inducks.org)
|
|
# The data presented here is based on information from the freely available Inducks database.
|
|
#
|
|
# This script is freely available to be modifiedy and redistributed
|
|
#
|
|
# !!!!!!!! BACKUP YOUR FILES BEFORE USING THIS SCRIPT !!!!!!!!! Yes, at least if you plan a mass scarping...
|
|
# Sorry guys, I cannot be held responsible if you screw your database...
|
|
#
|
|
# Some notes regarding the use of this script:
|
|
# Select 1 or more comics, same series; start the script and define the desired behavior.
|
|
# Pick the correct Series name for I.N.D.U.C.K.S., select which fields to fill:
|
|
# * a marked box means OVERRIDE ALWAYS *
|
|
# * a shaded box means OVERRIDE IF EMPTY *
|
|
# * a blank box means DO NOT OVERRIDE *
|
|
# On the Title label, clicking will change th way the title is written, from original to all initials capitalized
|
|
# Choose the genre if wanted, pick a translation language with a double click (characters' names will be set in that language, if existing)
|
|
# Click OK and wait...
|
|
# RESET will cycle the checkbox status
|
|
# REBUILD will rebuild/download the tables (tables are read once and then stored)
|
|
# CANCEL will abort the script
|
|
#
|
|
# Bugs, suggestions or comments in the Comicrack Forum !
|
|
#
|
|
#################################################################################################################
|
|
|
|
from __future__ import unicode_literals
|
|
|
|
import clr, re, sys, os, urlparse
|
|
|
|
from System.Diagnostics import Process
|
|
from System import *
|
|
from System.IO import *
|
|
from System.Threading import *
|
|
from System.Net import *
|
|
from System.Text import *
|
|
clr.AddReference('System')
|
|
clr.AddReference('System.Windows.Forms')
|
|
from System.Windows.Forms import *
|
|
clr.AddReference('System.Drawing')
|
|
from System.Drawing import Point, Size, ContentAlignment, Color, SystemColors, Icon
|
|
from datetime import datetime
|
|
import ssl, urllib
|
|
settings = ""
|
|
VERSION = "2.14"
|
|
|
|
DEBUG = False
|
|
#DEBUG = True
|
|
|
|
fileHandle = 0
|
|
|
|
SIZE_RENAME_LOG = 100000
|
|
SIZE_DEBUG_LOG = 100000
|
|
|
|
def FromDucks(books):
|
|
|
|
global settings, aList, StartPub, SelInd, TranslationID, LStart, DEBUG, TitleT
|
|
|
|
configpath = []
|
|
TranslationID = ""
|
|
StartPub = []
|
|
LStart = ""
|
|
|
|
TitleT = "L"
|
|
|
|
bdlogfile = Path.Combine(__file__[:-len('FromDucks.py')] , "FromDucks_Rename_Log.txt")
|
|
if FileInfo(bdlogfile).Exists and FileInfo(bdlogfile).Length > SIZE_RENAME_LOG:
|
|
Result = MessageBox.Show(ComicRack.MainWindow, "The File FromDucks_Rename_Log.txt is growing too much: do you want to clean it ?", "Rename Log File", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)
|
|
if Result == DialogResult.Yes:
|
|
File.Delete(bdlogfile)
|
|
|
|
debuglogfile = Path.Combine(__file__[:-len('FromDucks.py')] , "FromDucks_Debug_Log.txt")
|
|
if FileInfo(debuglogfile).Exists and FileInfo(debuglogfile).Length > SIZE_DEBUG_LOG:
|
|
Result = MessageBox.Show(ComicRack.MainWindow, "The File FromDucks_Debug_Log.txt is growing too much: do you want to clean it ?", "Debug Log File", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)
|
|
if Result == DialogResult.Yes:
|
|
File.Delete(debuglogfile)
|
|
|
|
Spath = sys.path[:]
|
|
del Spath[0]
|
|
|
|
#Just in case no paths were found
|
|
if not Spath:
|
|
MessageBox.Show("The script cannot find the locations of the scripts. Please try restarting ComicRack.")
|
|
return
|
|
|
|
configpath.append(__file__[:-len('FromDucks.py')] + "FromDucks.dat")
|
|
|
|
if not FileInfo(configpath[0]).Exists:
|
|
fileHandle = open(__file__[:-len('FromDucks.py')] + "FromDucks.dat", 'w')
|
|
fileHandle.write(" ")
|
|
fileHandle.close()
|
|
|
|
if FileInfo(configpath[0]).Length <= 1:
|
|
FillDat(True,None)
|
|
else:
|
|
FillDat(False,configpath)
|
|
|
|
for book in books:
|
|
StartPub.append(book.Series)
|
|
if book.LanguageISO == "en":
|
|
LStart = "us"
|
|
else:
|
|
LStart = book.LanguageISO
|
|
StartPub.append(LStart + "/" + book.Series[:1])
|
|
break
|
|
|
|
fileHandle = open(configpath[0], 'r')
|
|
pubDB = fileHandle.readlines()
|
|
fileHandle.close()
|
|
|
|
aList=list()
|
|
|
|
for x in pubDB:
|
|
if not x[1:] == "":
|
|
Data=x.split("^")
|
|
aList.append([Data[0],Data[1],Data[2],Data[3]])
|
|
|
|
import operator
|
|
aList.sort(key=operator.itemgetter(0,1))
|
|
|
|
bf = BuilderForm()
|
|
|
|
if bf.ShowDialog() == DialogResult.OK:
|
|
if (books):
|
|
|
|
if WorkerThread(books):
|
|
Monitor.Enter(ComicRack.MainWindow)
|
|
log_BD("\nAlbum(s) scraped !", "", 0)
|
|
log_BD("============= " + str(datetime.now().strftime("%A %d %B %Y %H:%M:%S")) + " =============", "\n\n", 0)
|
|
rdlg = MessageBox.Show(ComicRack.MainWindow, "Scrape Completed ! \n\nOpen Rename Log ?", "FromDucks", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)
|
|
if rdlg == DialogResult.Yes:
|
|
# open rename log automatically
|
|
if FileInfo(Path.Combine(__file__[:-len('FromDucks.py')] , "FromDucks_Rename_Log.txt")).Exists:
|
|
Process.Start (Path.Combine(__file__[:-len('FromDucks.py')] , "FromDucks_Rename_Log.txt"))
|
|
|
|
else:
|
|
Monitor.Enter(ComicRack.MainWindow)
|
|
log_BD("\n!! Errors in scraping !!", "", 0)
|
|
log_BD("============= " + str(datetime.now().strftime("%A %d %B %Y %H:%M:%S")) + " =============", "\n\n", 0)
|
|
rdlg = MessageBox.Show(ComicRack.MainWindow, "Scrape ended with errors ! \n\nOpen Debug Log ?", "FromDucks", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1)
|
|
if rdlg == DialogResult.Yes:
|
|
# open debug log automatically
|
|
if FileInfo(Path.Combine(__file__[:-len('FromDucks.py')] , "FromDucks_Debug_Log.txt")).Exists:
|
|
Process.Start (Path.Combine(__file__[:-len('FromDucks.py')] , "FromDucks_Debug_Log.txt"))
|
|
|
|
Monitor.Exit(ComicRack.MainWindow)
|
|
|
|
|
|
def WorkerThread(books):
|
|
|
|
global aUpdate, TranslationID, f, TitleT #, progress
|
|
|
|
try:
|
|
|
|
dTeams = ("TA", "BB", "TLP", "JW","SD", "BBB", "TTC","TMU", "Evrons", "CDR","Tempolizia", "UH", "Foul Fellows' Club", "101","S7", "QW", "SCPD", "Evil dwarfs", "DWM", "Justice Ducks")
|
|
|
|
# Read Language for Characternames
|
|
Translations = ""
|
|
if TranslationID == "":
|
|
TranslationID = 'en'
|
|
else:
|
|
TranslationID = TranslationID[:2]
|
|
|
|
# Read Characternames
|
|
if FileInfo(__file__[:-len('FromDucks.py')] + 'Characters.dat').Exists:
|
|
fileHandle = open(__file__[:-len('FromDucks.py')] + 'Characters.dat', 'r')
|
|
Translations = fileHandle.readlines()
|
|
fileHandle.close()
|
|
else:
|
|
MessageBox.Show("Translations of characters' name not available. Please REBUILD the tables!")
|
|
|
|
#progress = Stats()
|
|
#progress.CenterToParent()
|
|
#progress.Show()
|
|
|
|
nBook = 1
|
|
lErrors = True
|
|
log_BD("\n ** Scraping Started ** " + str(books.Count) + " Album(s)", "\n============ " + str(datetime.now().strftime("%A %d %B %Y %H:%M:%S")) + " ===========", 0)
|
|
|
|
f = ProgressBarDialog(books.Count)
|
|
f.Show(ComicRack.MainWindow)
|
|
|
|
for book in books:
|
|
Application.DoEvents()
|
|
|
|
#progress.modifyStats(nBook, TotBooks, book.Series, str(book.Number))
|
|
|
|
f.Update("[" + str(nBook) + "/" + str(len(books)) + "] : " + "[" + book.Series +"] #" + book.Number + " - " + book.Title, 1)
|
|
f.Refresh()
|
|
|
|
nBook += 1
|
|
|
|
Series,Day,Month,Year,Publisher,Pages,Language,Web,StoryFull,Characters,MainTitle = ReadInfoDucks(book)
|
|
#
|
|
if DEBUG:print chr(10) , "Scraped Info: " , Series,Day,Month,Year,Publisher,Pages,Language,Web,StoryFull,Characters,MainTitle
|
|
#
|
|
# series = 0 title = 1 team = 2 tags = 3 summary = 4 notes = 5 web = 6 chars = 7 year = 8 month = 9 publisher = 10
|
|
# editor = 11 penciller = 12 inker = 13 writer = 14 cover = 15 colorist = 16 letterer = 17 language = 18
|
|
# genre = 19 format = 20 location = 21 genret = 22
|
|
|
|
# if Series == 0:
|
|
|
|
# progress.Hide()
|
|
# return
|
|
|
|
if Series != -1:
|
|
|
|
if (aUpdate[0] == 1) or (aUpdate[0] == 2 and book.Series == ""):
|
|
try:
|
|
book.Series = Series.decode('utf-8')
|
|
except:
|
|
book.Series = Series
|
|
|
|
if (aUpdate[1] == 1) or (aUpdate[1] == 2 and book.Title == ""):
|
|
if MainTitle == "":
|
|
for x in StoryFull:
|
|
if TypeCol(x[0]) == "Story":
|
|
if TitleT == "T":
|
|
book.Title = x[2].title().strip("(").strip(")").replace("'S","'s").replace(" The"," the").replace("&Amp;","&") #.decode('utf-8')
|
|
else:
|
|
book.Title = x[2].strip("(").strip(")").replace("'S","'s").replace(" The"," the").replace("&Amp;","&") #.decode('utf-8')
|
|
break
|
|
else:
|
|
if TitleT == "T":
|
|
book.Title = MainTitle.title().strip("(").strip(")").replace("'S","'s").replace(" The "," the ").replace("&Amp;","&")
|
|
else:
|
|
book.Title = MainTitle.strip("(").strip(")").replace("'S","'s").replace(" The "," the ").replace("&Amp;","&")
|
|
|
|
if (aUpdate[4] == 1):
|
|
book.Summary = SumBuild(StoryFull)
|
|
if (aUpdate[4] == 2):
|
|
book.Summary = book.Summary + chr(10) * 2 + SumBuild(StoryFull)
|
|
|
|
if (aUpdate[5] == 1) or (aUpdate[5] == 2 and book.Notes == ""):
|
|
book.Notes = "Scraped from I.N.D.U.C.K.S. " + str(datetime.now())
|
|
|
|
if (aUpdate[6] == 1) or (aUpdate[6] == 2 and book.Web == ""):
|
|
book.Web = Web
|
|
|
|
if (aUpdate[7] == 1) or (aUpdate[7] == 2 and book.Characters == ""):
|
|
Charlist = ""
|
|
cTeams = ""
|
|
for x in Characters:
|
|
Chars = ""
|
|
CharName = x[0].replace("+","")
|
|
m0 = re.compile(CharName + '\^' + TranslationID + '\^(.*?)\^Y', re.IGNORECASE)
|
|
for Person in Translations:
|
|
result0 = m0.search(Person)
|
|
if result0:
|
|
try:
|
|
Chars = result0.group(1).decode('utf-8')
|
|
break
|
|
except:
|
|
pass
|
|
|
|
if Chars == "":
|
|
try:
|
|
Chars = x[1].decode('utf-8')
|
|
except:
|
|
Chars = x[1]
|
|
|
|
if Chars not in Charlist:
|
|
Charlist += Chars + ", "
|
|
if CharName in dTeams:
|
|
cTeams += Chars +", "
|
|
|
|
book.Characters = Charlist.strip(", ")
|
|
|
|
if ((aUpdate[2] == 1) or (aUpdate[2] == 2 and book.Teams == "")) and cTeams != "":
|
|
book.Teams = cTeams.strip(", ")
|
|
|
|
if (aUpdate[8] == 1) or (aUpdate[8] == 2 and book.Year == ""):
|
|
if Year == 0:
|
|
book.Year = -1
|
|
else:
|
|
book.Year = int(Year)
|
|
|
|
if (aUpdate[9] == 1) or (aUpdate[9] == 2 and book.Month == ""):
|
|
if Month == 0:
|
|
book.Month = -1
|
|
else:
|
|
book.Month = int(Month)
|
|
if Day == 0:
|
|
book.Day = -1
|
|
else:
|
|
try:
|
|
book.Day = int(Day)
|
|
except:
|
|
continue
|
|
|
|
if (aUpdate[10] == 1) or (aUpdate[10] == 2 and book.Publisher == ""):
|
|
try:
|
|
book.Publisher = Publisher.decode('utf-8')
|
|
except:
|
|
book.Publisher = Publisher
|
|
|
|
Writer,Penciller,Inker,CoverArtist,Letterer,Colorist = ArtBuild(StoryFull)
|
|
|
|
if (aUpdate[12] == 1) or (aUpdate[12] == 2 and book.Penciller == ""):
|
|
book.Penciller = Penciller
|
|
|
|
if (aUpdate[13] == 1) or (aUpdate[13] == 2 and book.Inker == ""):
|
|
book.Inker = Inker
|
|
|
|
if (aUpdate[14] == 1) or (aUpdate[14] == 2 and book.Writer == ""):
|
|
book.Writer = Writer
|
|
|
|
if (aUpdate[15] == 1) or (aUpdate[15] == 2 and book.CoverArtist == ""):
|
|
book.CoverArtist = CoverArtist
|
|
|
|
if (aUpdate[16] == 1) or (aUpdate[16] == 2 and book.Colorist == ""):
|
|
book.Colorist = Colorist
|
|
|
|
if (aUpdate[17] == 1) or (aUpdate[17] == 2 and book.Letterer == ""):
|
|
book.Letterer = Letterer
|
|
|
|
if (aUpdate[18] == 1) or (aUpdate[18] == 2 and book.LanguageISO == ""):
|
|
book.LanguageISO = Language
|
|
|
|
if (aUpdate[19] == 1) or (aUpdate[19] == 2 and book.Genre == ""):
|
|
try:
|
|
book.Genre = aUpdate[22].decode('utf-8')
|
|
except:
|
|
book.Genre = aUpdate[22]
|
|
|
|
elif Series == -1:
|
|
lErrors = False
|
|
debuglog()
|
|
|
|
log_BD("[" + book.Series +"] #" + book.Number + " - " + book.Title," ** Scraped **\n", 1 )
|
|
Application.DoEvents()
|
|
|
|
except:
|
|
f.Close()
|
|
debuglog()
|
|
return False
|
|
|
|
#progress.Hide()
|
|
f.Update("Completed !", 1)
|
|
f.Refresh()
|
|
f.Close()
|
|
|
|
return lErrors
|
|
|
|
class BuilderForm(Form):
|
|
|
|
def __init__(self):
|
|
global aUpdate, Translation, LStart
|
|
|
|
aUpdate = [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,""]
|
|
# series title team Tags summary Notes Web Chars year month publisher Editor
|
|
# Penciller Inker Writer Cover Artist Colorist Letterer Language Genre Format Location genret
|
|
|
|
self.ok = Button()
|
|
self.cancel = Button()
|
|
self.reset = Button()
|
|
self.rebuild = Button()
|
|
self.help = Button()
|
|
|
|
self.list = ListBox()
|
|
|
|
self.genret = TextBox()
|
|
self.translateinto = Label()
|
|
self.titleT = Label()
|
|
self.titleT.Tag = "L"
|
|
|
|
self.series = CheckBox()
|
|
self.year = CheckBox()
|
|
self.month = CheckBox()
|
|
self.title = CheckBox()
|
|
self.inker = CheckBox()
|
|
self.tags = CheckBox()
|
|
self.notes = CheckBox()
|
|
self.cover = CheckBox()
|
|
self.summary = CheckBox()
|
|
self.publisher = CheckBox()
|
|
self.penciller = CheckBox()
|
|
self.writer = CheckBox()
|
|
self.team = CheckBox()
|
|
self.web = CheckBox()
|
|
self.colorist = CheckBox()
|
|
self.language = CheckBox()
|
|
self.translate = Button()
|
|
self.translatelist = ListBox()
|
|
self.genre = CheckBox()
|
|
self.letterer = CheckBox()
|
|
self.location = CheckBox()
|
|
self.editor = CheckBox()
|
|
self.format = CheckBox()
|
|
self.age = CheckBox()
|
|
self.chars = CheckBox()
|
|
self.location = CheckBox()
|
|
|
|
#
|
|
# list
|
|
#
|
|
self.list.Location = Point(10, 10)
|
|
self.list.Name = "list"
|
|
self.list.Size = Size(175, 300)
|
|
self.list.TabIndex = 1
|
|
self.list.Text = "Publications"
|
|
self.list.MultiColumn = False
|
|
self.list.SelectionMode = SelectionMode.One
|
|
self.list.HorizontalScrollbar = True
|
|
self.list.DoubleClick += self.DoubleClickM
|
|
#self.list.Sorted = True
|
|
#
|
|
# ok
|
|
#
|
|
self.ok.DialogResult = DialogResult.OK
|
|
self.ok.Location = Point(405, 250)
|
|
self.ok.Name = "ok"
|
|
self.ok.Size = Size(75, 23)
|
|
self.ok.TabIndex = 2
|
|
self.ok.Text = "&Ok"
|
|
self.ok.UseVisualStyleBackColor = True
|
|
self.ok.Click += self.button_Click
|
|
self.ok.BackColor = Color.LightGreen
|
|
#
|
|
# cancel
|
|
#
|
|
self.cancel.DialogResult = DialogResult.Cancel
|
|
self.cancel.Location = Point(405, 275)
|
|
self.cancel.Name = "cancel"
|
|
self.cancel.Size = Size(75, 23)
|
|
self.cancel.TabIndex = 3
|
|
self.cancel.Text = "&Cancel"
|
|
self.cancel.UseVisualStyleBackColor = True
|
|
self.cancel.Click += self.button_Click
|
|
self.cancel.BackColor = Color.Red
|
|
#
|
|
# reset
|
|
#
|
|
self.reset.Location = Point(405, 10)
|
|
self.reset.Name = "reset"
|
|
self.reset.Size = Size(75, 23)
|
|
self.reset.TabIndex = 4
|
|
self.reset.Tag = "Reset the selections"
|
|
self.reset.Text = "&Reset"
|
|
self.reset.UseVisualStyleBackColor = True
|
|
self.reset.Click += self.button_Click
|
|
self.reset.BackColor = Color.LightYellow
|
|
#
|
|
# rebuild
|
|
#
|
|
self.rebuild.Location = Point(405, 40)
|
|
self.rebuild.Name = "rebuild"
|
|
self.rebuild.Size = Size(75, 23)
|
|
self.rebuild.TabIndex = 100
|
|
self.rebuild.Tag = "Rebuild the List"
|
|
self.rebuild.Text = "Re&build"
|
|
self.rebuild.UseVisualStyleBackColor = True
|
|
self.rebuild.Click += self.button_Click
|
|
self.rebuild.BackColor = Color.LightBlue
|
|
#
|
|
# Help
|
|
#
|
|
self.help.Location = Point(405, 70)
|
|
self.help.Name = "help"
|
|
self.help.Size = Size(75, 23)
|
|
self.help.TabIndex = 101
|
|
self.help.Tag = "General Help"
|
|
self.help.Text = "&Help"
|
|
self.help.UseVisualStyleBackColor = True
|
|
self.help.Click += self.button_Click
|
|
self.help.BackColor = Color.Yellow
|
|
#
|
|
# Genre Text
|
|
#
|
|
self.genret.Location = Point(375, 225)
|
|
self.genret.Name = "genret"
|
|
self.genret.Size = Size(85, 25)
|
|
self.genret.TabIndex = 27
|
|
self.genret.Text = "Disney"
|
|
#self.genret.TextAlign = MiddleCenter
|
|
#
|
|
# series
|
|
#
|
|
self.series.Location = Point(195, 25)
|
|
self.series.Name = "series"
|
|
self.series.Size = Size(103, 23)
|
|
self.series.TabIndex = 5
|
|
self.series.Tag = "Series"
|
|
self.series.Text = "Series"
|
|
self.series.UseVisualStyleBackColor = True
|
|
self.series.CheckState = CheckState.Indeterminate
|
|
self.series.ThreeState = True
|
|
#
|
|
# title
|
|
#
|
|
self.title.Location = Point(195, 50)
|
|
self.title.Name = "title"
|
|
self.title.Size = Size(20, 23)
|
|
self.title.TabIndex = 6
|
|
self.title.Tag = "Main Title"
|
|
self.title.Text = ""
|
|
self.title.UseVisualStyleBackColor = True
|
|
self.title.CheckState = CheckState.Indeterminate
|
|
self.title.ThreeState = True
|
|
#
|
|
# title label
|
|
#
|
|
self.titleT.Location = Point(213, 54)
|
|
self.titleT.Name = "titleT"
|
|
self.titleT.Size = Size(83, 23)
|
|
self.titleT.TabIndex = 300
|
|
self.titleT.Text = ">title<"
|
|
self.titleT.Click += self.ClickT
|
|
#
|
|
# team
|
|
#
|
|
self.team.Location = Point(195, 75)
|
|
self.team.Name = "team"
|
|
self.team.Size = Size(103, 23)
|
|
self.team.TabIndex = 7
|
|
self.team.Tag = "Team"
|
|
self.team.Text = "Team"
|
|
self.team.UseVisualStyleBackColor = True
|
|
self.team.CheckState = CheckState.Indeterminate
|
|
self.team.ThreeState = True
|
|
# Team Button
|
|
#self.teamlist.Location = Point(405, 75)
|
|
#self.teamlist.Name = "teamlist"
|
|
#self.teamlist.Size = Size(75, 23)
|
|
#self.teamlist.TabIndex = 28
|
|
#self.teamlist.Tag = "TeamList"
|
|
#self.teamlist.Text = "Team List"
|
|
#self.teamlist.UseVisualStyleBackColor = True
|
|
#self.teamlist.Click += self.button_Click
|
|
#
|
|
# Tags
|
|
#
|
|
self.tags.Location = Point(195, 100)
|
|
self.tags.Name = "tags"
|
|
self.tags.Size = Size(103, 23)
|
|
self.tags.TabIndex = 8
|
|
self.tags.Tag = "Tags"
|
|
self.tags.Text = "Tags"
|
|
self.tags.UseVisualStyleBackColor = True
|
|
self.tags.CheckState = CheckState.Indeterminate
|
|
self.tags.ThreeState = True
|
|
#
|
|
# summary
|
|
#
|
|
self.summary.Location = Point(195, 125)
|
|
self.summary.Name = "summary"
|
|
self.summary.Size = Size(103, 23)
|
|
self.summary.TabIndex = 9
|
|
self.summary.Tag = "Summary"
|
|
self.summary.Text = "Summary"
|
|
self.summary.UseVisualStyleBackColor = True
|
|
self.summary.CheckState = CheckState.Indeterminate
|
|
self.summary.ThreeState = True
|
|
#
|
|
# Notes
|
|
#
|
|
self.notes.Location = Point(195, 150)
|
|
self.notes.Name = "notes"
|
|
self.notes.Size = Size(103, 23)
|
|
self.notes.TabIndex = 10
|
|
self.notes.Tag = "Notes"
|
|
self.notes.Text = "Notes"
|
|
self.notes.UseVisualStyleBackColor = True
|
|
self.notes.CheckState = CheckState.Indeterminate
|
|
self.notes.ThreeState = True
|
|
#
|
|
# Web
|
|
#
|
|
self.web.Location = Point(195, 175)
|
|
self.web.Name = "web"
|
|
self.web.Size = Size(103, 23)
|
|
self.web.TabIndex = 11
|
|
self.web.Tag = "Web"
|
|
self.web.Text = "Web"
|
|
self.web.UseVisualStyleBackColor = True
|
|
self.web.CheckState = CheckState.Indeterminate
|
|
self.web.ThreeState = True
|
|
#
|
|
# Chars
|
|
#
|
|
self.chars.Location = Point(195, 200)
|
|
self.chars.Name = "chars"
|
|
self.chars.Size = Size(103, 23)
|
|
self.chars.TabIndex = 12
|
|
self.chars.Tag = "Characters"
|
|
self.chars.Text = "Characters"
|
|
self.chars.UseVisualStyleBackColor = True
|
|
self.chars.CheckState = CheckState.Indeterminate
|
|
self.chars.ThreeState = True
|
|
#
|
|
# year
|
|
#
|
|
self.year.Location = Point(195, 225)
|
|
self.year.Name = "year"
|
|
self.year.Size = Size(103, 23)
|
|
self.year.TabIndex = 13
|
|
self.year.Tag = "Year"
|
|
self.year.Text = "Year"
|
|
self.year.UseVisualStyleBackColor = True
|
|
self.year.CheckState = CheckState.Indeterminate
|
|
self.year.ThreeState = True
|
|
#
|
|
# month
|
|
#
|
|
self.month.Location = Point(195, 250)
|
|
self.month.Name = "month"
|
|
self.month.Size = Size(103, 23)
|
|
self.month.TabIndex = 14
|
|
self.month.Tag = "Month"
|
|
self.month.Text = "Month"
|
|
self.month.UseVisualStyleBackColor = True
|
|
self.month.CheckState = CheckState.Indeterminate
|
|
self.month.ThreeState = True
|
|
#
|
|
# publisher
|
|
#
|
|
self.publisher.Location = Point(195, 275)
|
|
self.publisher.Name = "publisher"
|
|
self.publisher.Size = Size(103, 23)
|
|
self.publisher.TabIndex = 15
|
|
self.publisher.Tag = "Publisher"
|
|
self.publisher.Text = "Publisher"
|
|
self.publisher.UseVisualStyleBackColor = True
|
|
self.publisher.CheckState = CheckState.Indeterminate
|
|
self.publisher.ThreeState = True
|
|
#
|
|
# Editor
|
|
#
|
|
self.editor.Location = Point(300, 25)
|
|
self.editor.Name = "editor"
|
|
self.editor.Size = Size(103, 23)
|
|
self.editor.TabIndex = 16
|
|
self.editor.Tag = "Editor"
|
|
self.editor.Text = "Editor"
|
|
self.editor.UseVisualStyleBackColor = True
|
|
self.editor.CheckState = CheckState.Indeterminate
|
|
self.editor.ThreeState = True
|
|
#
|
|
# Penciller
|
|
#
|
|
self.penciller.Location = Point(300, 50)
|
|
self.penciller.Name = "penciller"
|
|
self.penciller.Size = Size(103, 23)
|
|
self.penciller.TabIndex = 17
|
|
self.penciller.Tag = "Penciller"
|
|
self.penciller.Text = "Penciller"
|
|
self.penciller.UseVisualStyleBackColor = True
|
|
self.penciller.CheckState = CheckState.Indeterminate
|
|
self.penciller.ThreeState = True
|
|
#
|
|
# Inker
|
|
#
|
|
self.inker.Location = Point(300, 75)
|
|
self.inker.Name = "inker"
|
|
self.inker.Size = Size(103, 23)
|
|
self.inker.TabIndex = 18
|
|
self.inker.Tag = "Inker"
|
|
self.inker.Text = "Inker"
|
|
self.inker.UseVisualStyleBackColor = True
|
|
self.inker.CheckState = CheckState.Indeterminate
|
|
self.inker.ThreeState = True
|
|
#
|
|
# Writer
|
|
#
|
|
self.writer.Location = Point(300, 100)
|
|
self.writer.Name = "writer"
|
|
self.writer.Size = Size(103, 23)
|
|
self.writer.TabIndex = 19
|
|
self.writer.Tag = "Writer"
|
|
self.writer.Text = "Writer"
|
|
self.writer.UseVisualStyleBackColor = True
|
|
self.writer.CheckState = CheckState.Indeterminate
|
|
self.writer.ThreeState = True
|
|
#
|
|
# Cover Artist
|
|
#
|
|
self.cover.Location = Point(300, 125)
|
|
self.cover.Name = "cover"
|
|
self.cover.Size = Size(103, 23)
|
|
self.cover.TabIndex = 20
|
|
self.cover.Tag = "Cover Artist"
|
|
self.cover.Text = "Cover Artist"
|
|
self.cover.UseVisualStyleBackColor = True
|
|
self.cover.CheckState = CheckState.Indeterminate
|
|
self.cover.ThreeState = True
|
|
#
|
|
# Colorist
|
|
#
|
|
self.colorist.Location = Point(300, 150)
|
|
self.colorist.Name = "colorist"
|
|
self.colorist.Size = Size(103, 23)
|
|
self.colorist.TabIndex = 21
|
|
self.colorist.Tag = "Colorist"
|
|
self.colorist.Text = "Colorist"
|
|
self.colorist.UseVisualStyleBackColor = True
|
|
self.colorist.CheckState = CheckState.Indeterminate
|
|
self.colorist.ThreeState = True
|
|
#
|
|
# Letterer
|
|
#
|
|
self.letterer.Location = Point(300, 175)
|
|
self.letterer.Name = "letterer"
|
|
self.letterer.Size = Size(103, 23)
|
|
self.letterer.TabIndex = 22
|
|
self.letterer.Tag = "Letterer"
|
|
self.letterer.Text = "Letterer"
|
|
self.letterer.UseVisualStyleBackColor = True
|
|
self.letterer.CheckState = CheckState.Indeterminate
|
|
self.letterer.ThreeState = True
|
|
#
|
|
# Language
|
|
#
|
|
self.language.Location = Point(300, 200)
|
|
self.language.Name = "language"
|
|
self.language.Size = Size(103, 23)
|
|
self.language.TabIndex = 23
|
|
self.language.Tag = "Language"
|
|
self.language.Text = "Language"
|
|
self.language.UseVisualStyleBackColor = True
|
|
self.language.CheckState = CheckState.Indeterminate
|
|
self.language.ThreeState = True
|
|
#
|
|
# Translate Button
|
|
self.translate.Location = Point(405, 100)
|
|
self.translate.Name = "translate"
|
|
self.translate.Size = Size(75, 23)
|
|
self.translate.TabIndex = 28
|
|
self.translate.Tag = "Translate"
|
|
self.translate.Text = "Translate"
|
|
self.translate.UseVisualStyleBackColor = True
|
|
self.translate.Click += self.button_Click
|
|
#
|
|
# Translatelist
|
|
#
|
|
self.translatelist.Location = Point(405, 125)
|
|
self.translatelist.Name = "translatelist"
|
|
self.translatelist.Size = Size(75, 100)
|
|
self.translatelist.TabIndex = 29
|
|
self.translatelist.Text = "Translation Language"
|
|
self.translatelist.MultiColumn = False
|
|
self.translatelist.SelectionMode = SelectionMode.One
|
|
self.translatelist.HorizontalScrollbar = True
|
|
self.translatelist.DoubleClick += self.DoubleClick
|
|
#
|
|
# Translateinto label
|
|
#
|
|
self.translateinto.Location = Point(405, 125)
|
|
self.translateinto.Name = "translateinto"
|
|
self.translateinto.Size = Size(75, 100)
|
|
self.translateinto.TabIndex = 30
|
|
self.translateinto.Text = ""
|
|
#
|
|
# Genre
|
|
#
|
|
self.genre.Location = Point(300, 225)
|
|
self.genre.Name = "genre"
|
|
self.genre.Size = Size(103, 23)
|
|
self.genre.TabIndex = 24
|
|
self.genre.Tag = "Genre"
|
|
self.genre.Text = "Genre"
|
|
self.genre.UseVisualStyleBackColor = True
|
|
self.genre.CheckStateChanged += self.ChangeStatus
|
|
self.genre.CheckState = CheckState.Indeterminate
|
|
self.genre.ThreeState = True
|
|
#
|
|
# Format
|
|
#
|
|
self.format.Location = Point(300, 250)
|
|
self.format.Name = "format"
|
|
self.format.Size = Size(103, 23)
|
|
self.format.TabIndex = 25
|
|
self.format.Tag = "Format"
|
|
self.format.Text = "Format"
|
|
self.format.UseVisualStyleBackColor = True
|
|
self.format.CheckState = CheckState.Indeterminate
|
|
self.format.ThreeState = True
|
|
#
|
|
# Location
|
|
#
|
|
self.location.Location = Point(300, 275)
|
|
self.location.Name = "location"
|
|
self.location.Size = Size(103, 23)
|
|
self.location.TabIndex = 26
|
|
self.location.Tag = "Location"
|
|
self.location.Text = "Location"
|
|
self.location.UseVisualStyleBackColor = True
|
|
self.location.CheckState = CheckState.Indeterminate
|
|
self.location.ThreeState = True
|
|
#
|
|
# box W > x L V
|
|
self.ClientSize = Size(490, 315)
|
|
#
|
|
self.Controls.Add(self.cancel)
|
|
self.Controls.Add(self.ok)
|
|
self.Controls.Add(self.reset)
|
|
self.Controls.Add(self.rebuild)
|
|
self.Controls.Add(self.help)
|
|
|
|
self.Controls.Add(self.genret)
|
|
|
|
self.Controls.Add(self.series)
|
|
self.Controls.Add(self.publisher)
|
|
self.Controls.Add(self.title)
|
|
self.Controls.Add(self.titleT)
|
|
self.Controls.Add(self.month)
|
|
self.Controls.Add(self.year)
|
|
self.Controls.Add(self.tags)
|
|
self.Controls.Add(self.inker)
|
|
self.Controls.Add(self.writer)
|
|
self.Controls.Add(self.penciller)
|
|
self.Controls.Add(self.team)
|
|
self.Controls.Add(self.cover)
|
|
self.Controls.Add(self.summary)
|
|
self.Controls.Add(self.notes)
|
|
|
|
self.Controls.Add(self.web)
|
|
self.Controls.Add(self.colorist)
|
|
self.Controls.Add(self.language)
|
|
self.Controls.Add(self.translate)
|
|
self.Controls.Add(self.genre)
|
|
self.Controls.Add(self.letterer)
|
|
self.Controls.Add(self.editor)
|
|
self.Controls.Add(self.chars)
|
|
self.Controls.Add(self.format)
|
|
self.Controls.Add(self.location)
|
|
|
|
self.list.BeginUpdate()
|
|
#
|
|
# remove first element
|
|
#
|
|
nIndex = 0
|
|
aList.pop(0)
|
|
|
|
for x in range(len(aList)):
|
|
try:
|
|
self.list.Items.Add(aList[x][0] + " - " + aList[x][3].decode('utf-8'))
|
|
except:
|
|
self.list.Items.Add(aList[x][0] + " - " + aList[x][3])
|
|
|
|
try:
|
|
if StartPub[0] == aList[x][3].decode('utf-8') and StartPub[1][:2] == LStart:
|
|
nIndex = x
|
|
except:
|
|
if StartPub[0] == aList[x][3] and StartPub[1][:2] == LStart:
|
|
nIndex = x
|
|
|
|
self.Controls.Add(self.list)
|
|
|
|
if nIndex > 0:
|
|
self.list.SelectedIndex = nIndex
|
|
else:
|
|
self.list.SelectedIndex = self.list.FindString(StartPub[1])
|
|
|
|
self.list.TopIndex = self.list.SelectedIndex
|
|
|
|
self.list.Focus()
|
|
|
|
#self.list.ScrollIntoView(1) #self.list.Items[self.list.SelectedIndex])
|
|
|
|
self.list.EndUpdate()
|
|
|
|
self.FormBorderStyle = FormBorderStyle.FixedDialog
|
|
self.Name = "FromDucks"
|
|
self.StartPosition = FormStartPosition.CenterParent
|
|
self.Text = "(c) Inducks team (web: coa.inducks.org)"
|
|
self.MinimizeBox = False
|
|
self.MaximizeBox = False
|
|
|
|
|
|
def button_Click(self, sender, e):
|
|
|
|
global aUpdate, SelInd
|
|
|
|
if sender.Name.CompareTo(self.ok.Name) == 0:
|
|
SelInd = self.list.SelectedIndex
|
|
dDict = {"Checked": 1, "Unchecked": 0, "Indeterminate": 2 }
|
|
for x in range(self.Controls.Count):
|
|
if 4 < self.Controls.Item[x].TabIndex < 27:
|
|
aUpdate[self.Controls.Item[x].TabIndex- 5] = dDict[self.Controls.Item[x].CheckState.ToString()]
|
|
aUpdate[22] = self.genret.Text
|
|
|
|
elif sender.Name.CompareTo(self.reset.Name) == 0:
|
|
for x in range(self.Controls.Count):
|
|
if 4 < self.Controls.Item[x].TabIndex < 27:
|
|
aUpdate[self.Controls.Item[x].TabIndex-5] = aUpdate[self.Controls.Item[x].TabIndex-5] + 1
|
|
if aUpdate[self.Controls.Item[x].TabIndex-5] == 3:
|
|
aUpdate[self.Controls.Item[x].TabIndex-5] = 0
|
|
if self.Controls.Item[x].CheckState == CheckState.Checked:
|
|
self.Controls.Item[x].CheckState = CheckState.Unchecked
|
|
elif self.Controls.Item[x].CheckState == CheckState.Unchecked:
|
|
self.Controls.Item[x].CheckState = CheckState.Indeterminate
|
|
else:
|
|
self.Controls.Item[x].CheckState = CheckState.Checked
|
|
|
|
self.translateinto.Visible = False
|
|
self.translateinto.Text = ""
|
|
TranslationID = ""
|
|
|
|
elif sender.Name.CompareTo(self.rebuild.Name) == 0:
|
|
FillDat(True, None)
|
|
|
|
elif sender.Name.CompareTo(self.cancel.Name) == 0:
|
|
pass
|
|
|
|
elif sender.Name.CompareTo(self.translate.Name) == 0:
|
|
self.translatelist.BeginUpdate()
|
|
if self.translatelist.Visible == False:
|
|
|
|
self.translatelist.Visible = True
|
|
self.translateinto.Text = ""
|
|
self.translateinto.Visible = False
|
|
|
|
if FileInfo(__file__[:-len('FromDucks.py')] + 'Languages.dat').Exists:
|
|
fileHandle = open(__file__[:-len('FromDucks.py')] + 'Languages.dat', 'r')
|
|
AllLanguages = fileHandle.readlines()
|
|
fileHandle.close()
|
|
AllLanguages.pop(0)
|
|
for x in AllLanguages:
|
|
cList = x.split("^")
|
|
self.translatelist.Items.Add(cList[0].upper() + " - " + cList[2] )
|
|
self.Controls.Add(self.translatelist)
|
|
self.translatelist.EndUpdate()
|
|
else:
|
|
MessageBox.Show('REBUILD the local tables!')
|
|
|
|
elif sender.Name.CompareTo(self.help.Name) == 0:
|
|
MessageBox.Show('Help - FromDucks Script v' + VERSION + "\n---------------------\n" +
|
|
"Select 1 or more comics, same series;\nStart the script and define the desired behavior.\n" +
|
|
"Pick the correct Series name for COA, select which fields to fill:\n" +
|
|
"* A marked box means OVERRIDE ALWAYS *\n" +
|
|
"* A shaded box means OVERRIDE IF EMPTY *\n" +
|
|
"(only for SUMMARY, it will add to the current value)\n" +
|
|
"* A blank box means DO NOT OVERRIDE *\n" +
|
|
"On the Title label, clicking will change the way the title is written, from original to all initials capitalized\n" +
|
|
"Choose the genre if needed and a translation language with a double click\n"+
|
|
"(characters' names will be set in that language, if existing)\n" +
|
|
"\nDouble clicking on a series will show the COA Webpage;\n" +
|
|
"Click OK and wait...\n" +
|
|
"> RESET will cycle the checkbox status\n" +
|
|
"> REBUILD will rebuild the Series list\n(the Series list is read once and then stored);\n" +
|
|
"> CANCEL will abort the script")
|
|
|
|
def ChangeStatus(self, sender, e):
|
|
|
|
if sender.Name.CompareTo(self.genre.Name) == 0:
|
|
stDict = {"Checked": True, "Unchecked": False, "Indeterminate": True }
|
|
self.genret.Enabled = stDict[sender.CheckState.ToString()]
|
|
else:
|
|
pass
|
|
|
|
def DoubleClickM(self, sender, e):
|
|
|
|
global aList
|
|
|
|
Code = aList[self.list.SelectedIndex][0]
|
|
cWeb = "https://coa.inducks.org/publication.php?c="
|
|
|
|
DCWeb = cWeb + Code
|
|
if DEBUG:print "Series in Web:", DCWeb
|
|
Process.Start(DCWeb)
|
|
|
|
def DoubleClick(self, sender, e):
|
|
global TranslationID
|
|
|
|
if self.translateinto.Visible == False:
|
|
self.translateinto.Visible = True
|
|
TranslationID = self.translatelist.SelectedItem
|
|
self.translatelist.Visible = False
|
|
self.Controls.Add(self.translateinto)
|
|
self.translateinto.Text = self.translatelist.SelectedItem[self.translatelist.SelectedItem.find(" ")+2:].strip(" ")
|
|
|
|
def ClickT(self, sender, e):
|
|
global TitleT
|
|
|
|
if self.titleT.Tag == "T":
|
|
self.titleT.Text = ">title<"
|
|
self.titleT.Tag = "L"
|
|
TitleT = "L"
|
|
else:
|
|
self.titleT.Text = ">TiTlE<"
|
|
self.titleT.Tag = "T"
|
|
TitleT = "T"
|
|
|
|
def ReadInfoDucks(book):
|
|
|
|
global aList, SelInd, TranslationID, f #, progress
|
|
|
|
cSeries = aList[SelInd][0].strip()
|
|
|
|
# Read inducks
|
|
cWeb = 'https://inducks.org/issue.php?c='
|
|
#
|
|
if DEBUG:print "Searching ---->" , aList[SelInd][3]
|
|
#
|
|
|
|
nNumIss = str(book.Number).strip().replace(" ","%20").replace("/","%2F")
|
|
contents = ""
|
|
for counter in range (0,4):
|
|
try:
|
|
nNum = cSeries + "+" * counter + nNumIss
|
|
#nNum = cSeries + "%20" + nNumIss
|
|
|
|
try:
|
|
pr = cWeb + nNum
|
|
|
|
#req = urllib2.Request.(pr)
|
|
contents = _read_url(pr.encode('utf-8'))
|
|
|
|
except:
|
|
debuglog()
|
|
continue
|
|
|
|
#if not "Issue not found" in contents:
|
|
if len(contents)>4000:
|
|
break
|
|
|
|
except IOError:
|
|
f.Update("Not Found: N." + str(nNum), 1)
|
|
f.Refresh()
|
|
#
|
|
if DEBUG:print "Not Found ----> n. " , nNum.replace("+","")
|
|
debuglog()
|
|
#
|
|
return -1,0,0,0,0,0,0,0,0,0,0
|
|
|
|
if len(contents)<4000:
|
|
f.Update("Not Found: N." + str(nNum), 1)
|
|
f.Refresh()
|
|
#
|
|
if DEBUG:print "Not Found ----> n. " , nNum.replace("+","")
|
|
debuglog()
|
|
#
|
|
return -1,0,0,0,0,0,0,0,0,0,0
|
|
|
|
#try:
|
|
# fileHandle.close()
|
|
#except:
|
|
# pass
|
|
#
|
|
if DEBUG:print "Web ----------> " + cWeb + cSeries
|
|
|
|
#
|
|
|
|
# Read Language
|
|
Language = aList[SelInd][2]
|
|
# Read Web
|
|
#Web = cWeb + cSeries + nNum
|
|
Web = cWeb + nNum
|
|
|
|
#
|
|
if DEBUG:print "Language -----> " + Language
|
|
#
|
|
|
|
# Read data
|
|
#m0 = re.compile(r'Publication:\s<a href=\"publication.php\?c=[a-z]{2,3}[/][^">]*?\">(.*?)</a>', re.IGNORECASE | re.MULTILINE | re.DOTALL)
|
|
m0 = re.compile(r'Publication<.*?<a\shref=\"publication\.php\?c=[a-z]{2,3}[%2][^">]*?\">(.*?)<', re.IGNORECASE | re.MULTILINE | re.DOTALL)
|
|
m1 = re.compile(r'Publisher.*?<a\shref=\"publisher.php\?c=.*?\">(.*?)<', re.IGNORECASE | re.MULTILINE | re.DOTALL)
|
|
m1a = re.compile(r'Title<\/dt>\s*?<dd>(.*?)<', re.IGNORECASE | re.MULTILINE | re.DOTALL)
|
|
m2 = re.compile(r'Date<\/dt>\s*?<dd>(.*?)>', re.IGNORECASE | re.MULTILINE | re.DOTALL)
|
|
m3 = re.compile(r'Pages<\/dt>\s*?<dd>(\d*?)<', re.IGNORECASE | re.MULTILINE | re.DOTALL)
|
|
|
|
result0 = m0.search(contents)
|
|
Series = ""
|
|
if result0:
|
|
Series = result0.group(1)
|
|
else:
|
|
#progress.NotFound("n." + str(nNum))
|
|
f.Update("Not Found: N." + str(nNum), 1)
|
|
f.Refresh()
|
|
#
|
|
if DEBUG:print "Not Found ----> n. " , nNum.replace("+","")
|
|
debuglog()
|
|
#
|
|
return -1,0,0,0,0,0,0,0,0,0,0
|
|
|
|
#
|
|
if DEBUG:print "Series -------> " + Series
|
|
#
|
|
|
|
result1 = m1.search(contents)
|
|
Publisher = ""
|
|
if result1:
|
|
Publisher = result1.group(1)
|
|
|
|
#
|
|
if DEBUG:print "Publisher ----> " + Publisher
|
|
#
|
|
|
|
result1a = m1a.search(contents)
|
|
MainTitle = ""
|
|
if result1a:
|
|
try:
|
|
MainTitle = result1a.group(1).decode('utf-8')
|
|
except:
|
|
MainTitle = result1a.group(1)
|
|
|
|
#
|
|
if DEBUG:print "Main Title ---> " + MainTitle#.decode('utf-8')
|
|
#
|
|
|
|
result2 = m2.search(contents)
|
|
|
|
Day = 0
|
|
Month = 0
|
|
Year = 0
|
|
|
|
if result2:
|
|
if "<time datetime=" in result2.group(1):
|
|
Day = result2.group(1)[24:26] # mid
|
|
Month = result2.group(1)[21:23] # mid
|
|
Year = result2.group(1)[16:20] # mid
|
|
else:
|
|
Day = 0
|
|
d1 = re.compile(r'([\D]{0,10})\s')
|
|
d2 = re.compile(r'([0-9]{4})')
|
|
resultd1 = d1.search(result2.group(1))
|
|
resultd2 = d2.search(result2.group(1))
|
|
if resultd1:
|
|
Month = MonthNum(resultd1.group(1))
|
|
if resultd2:
|
|
Year = resultd2.group(1)
|
|
|
|
#
|
|
if DEBUG:print "Day -------->" , Day
|
|
if DEBUG:print "Month -------->" , Month
|
|
if DEBUG:print "Year -------->" , Year
|
|
#
|
|
|
|
result3 = m3.search(contents)
|
|
Pages = 0
|
|
if result3:
|
|
Pages = result3.group(1)
|
|
|
|
#
|
|
if DEBUG:print "Pages -------->" , Pages
|
|
#
|
|
|
|
# Read Stories data
|
|
m3 = re.compile(r'<td\svalign=\"middle\"\sbgcolor=\"#(.*?)add\sa\sscan', re.S)
|
|
m4 = re.compile(r'(.*?)\">(?:.*?)<a\shref=\"story\.php\?c=(.*?)\">(?:.*?)<i>(.*?)</i>', re.S)
|
|
#m5 = re.compile(r'story.php\?c=(.[^>]*?)\"><font')
|
|
#m6 = re.compile(r'<td><small>(?:.*?)<i>(.*?)</i><br/>',re.S)
|
|
m7 = re.compile(r'</small>\n<td>(.*?)<td>', re.S)
|
|
#m7 = re.compile(r'/small></td>[\r\n]*?<td>\s(.*?)</td>', re.S)
|
|
m7a = re.compile(r'(Writing|Idea|Text|Pencils|Colours|Art|Ink|Script|Plot|Lettering):\s<a\shref=\"creator\.php\?c=.*?\">(.*?)</a>')
|
|
m8 = re.compile(r'(?:Appearances:\s)(.*?)<br/>')
|
|
m8a = re.compile(r'(?:php\?c=(.*?)\">)(.*?)</a>')
|
|
|
|
Type = ""
|
|
Story = ""
|
|
Title = ""
|
|
Artists =[]
|
|
Appearances = []
|
|
Characters = []
|
|
StoryFull = []
|
|
|
|
nl=0
|
|
if DEBUG:print chr(10) + "<-------- Stories -------->"
|
|
|
|
result3 = m3.findall(contents)
|
|
# if not result3:
|
|
# #progress.NotFound("stories")
|
|
# f.Update("Stories", 1)
|
|
# f.Refresh()
|
|
# #
|
|
# if DEBUG:print "Not Found ----> Stories"
|
|
# #
|
|
# return -1,0,0,0,0,0,0,0,0,0,0
|
|
|
|
|
|
for Stories in result3:
|
|
|
|
Type = ""
|
|
Story = ""
|
|
Title = ""
|
|
|
|
result4 = m4.search(Stories)
|
|
if result4:
|
|
Type = result4.group(1)
|
|
try:
|
|
Story = result4.group(2).decode('utf-8').replace('<','<').replace('>','>').replace('"','"').replace(''',"'").replace('%2F',"/")
|
|
except:
|
|
Story = result4.group(2).replace('<','<').replace('>','>').replace('"','"').replace(''',"'").replace('%2F',"/")
|
|
try:
|
|
Title = result4.group(3).decode('utf-8').replace('<','<').replace('>','>').replace('"','"').replace(''',"'").replace('%2F;',"/")
|
|
except:
|
|
Title = result4.group(3).replace('<','<').replace('>','>').replace('"','"').replace(''',"'").replace('%2F;',"/")
|
|
#
|
|
if DEBUG:print chr(10) + "Type ---------> " + TypeCol(Type)
|
|
#
|
|
if DEBUG:print "Story # ------> " + Story
|
|
#
|
|
if DEBUG:print "Title --------> " + Title #.decode('utf-8')
|
|
#
|
|
|
|
result7 = m7.search(Stories)
|
|
if result7:
|
|
result7a = m7a.findall(result7.group(1))
|
|
if result7a:
|
|
for Artist in result7a:
|
|
try:
|
|
Artists.append(Artist[0] + "^" + Artist[1].decode('utf-8'))
|
|
except:
|
|
Artists.append(Artist[0] + "^" + Artist[1])
|
|
#
|
|
if DEBUG:print "Artists ------> "
|
|
for all in Artists:
|
|
if DEBUG:print " " * 16 + all.replace("^",": ")
|
|
#
|
|
|
|
result8 = m8.findall(Stories)
|
|
if result8:
|
|
for Char in result8[0].split(','):
|
|
result8a = m8a.search(Char)
|
|
if result8a:
|
|
Appearances.append([result8a.group(1),result8a.group(2)])
|
|
|
|
for x in Appearances:
|
|
if x[0] not in Characters:
|
|
#Characters.append([x[0],x[1].decode('utf-8')])
|
|
Characters.append([x[0],x[1]])
|
|
|
|
#
|
|
if DEBUG:print "Characters ---> "
|
|
for all in Appearances:
|
|
try:
|
|
if DEBUG:print " " * 16 + all[1].decode('utf-8')
|
|
except:
|
|
if DEBUG:print " " * 16 + all[1]
|
|
#
|
|
|
|
StoryFull.append([Type,Story,Title,Artists])
|
|
|
|
Artists = []
|
|
Appearances = []
|
|
|
|
|
|
|
|
nl+=1
|
|
if nl>50:
|
|
break
|
|
|
|
return Series,Day,Month,Year,Publisher,Pages,Language,Web,StoryFull,Characters,MainTitle
|
|
|
|
def SumBuild(StoryFull):
|
|
|
|
global TitleT
|
|
|
|
cNotes=""
|
|
cArt = ""
|
|
# Writing|Idea||Text|Pencils|Colours|Art|Ink|Script|Plot|Lettering
|
|
for story in StoryFull:
|
|
cArt = ""
|
|
for Art in range (len(story[3])):
|
|
Job,Auth = (story[3][Art]).split("^")
|
|
if Job in ("Writing", "Plot", "Script", "Text", "Idea"):
|
|
cArt += " W: " + Auth
|
|
if Job in ("Art", "Pencils"):
|
|
cArt += " P: " + Auth
|
|
if Job == "Ink":
|
|
cArt += " I: " + Auth
|
|
if Job == "Lettering":
|
|
cArt += " L: " + Auth
|
|
if Job == "Colours":
|
|
cArt += " C: " + Auth
|
|
|
|
if story[0] != "":
|
|
cNotes += TypeCol(story[0])
|
|
if story[1] != "":
|
|
cNotes += ": " + story[1].replace('+',' ')
|
|
if story[2] != "":
|
|
if TitleT == "T":
|
|
cNotes += " - " + story[2].title().strip("(").strip(")").replace("'S","'s").replace(" The"," the").replace("&Amp;","&") #.decode('utf-8')
|
|
else:
|
|
cNotes += " - " + story[2].strip("(").strip(")").replace("'S","'s").replace(" The"," the").replace("&Amp;","&") #.decode('utf-8')
|
|
if cArt != "":
|
|
cNotes += " (" + cArt.strip() + ")"
|
|
if cNotes != "":
|
|
cNotes += "\n"
|
|
|
|
return cNotes
|
|
|
|
def ArtBuild(StoryFull):
|
|
|
|
cInk =""
|
|
cWri = ""
|
|
cPen = ""
|
|
cLett = ""
|
|
cColour = ""
|
|
cCover = ""
|
|
|
|
for story in StoryFull:
|
|
for Art in range (len(story[3])):
|
|
Job, Auth = (story[3][Art]).split("^")
|
|
if TypeCol(story[0]) == "Cover" and Auth not in cCover:
|
|
cCover += Auth + ", "
|
|
if Job in ("Writing", "Plot", "Script", "Text", "Idea") and Auth not in cWri:
|
|
cWri += Auth + ", "
|
|
elif Job in ("Art", "Pencils") and Auth not in cPen:
|
|
cPen += Auth + ", "
|
|
elif Job == "Ink" and Auth not in cInk:
|
|
cInk += Auth + ", "
|
|
elif Job == "Lettering" and Auth not in cLett:
|
|
cLett += Auth + ", "
|
|
elif Job == "Colours" and Auth not in cColour:
|
|
cColour += Auth + ", "
|
|
|
|
return cWri.strip(", "),cPen.strip(", " ),cInk.strip(", "),cCover.strip(", "),cLett.strip(", "),cColour.strip(", ")
|
|
|
|
def TypeCol(Type):
|
|
|
|
if Type == 'cbdced':
|
|
cType="Story"
|
|
elif Type == 'ffcc33':
|
|
cType="Cover"
|
|
elif Type == 'cccc99':
|
|
cType="Article"
|
|
elif Type == 'ff99ff':
|
|
cType="Gag"
|
|
else:
|
|
cType="Other"
|
|
|
|
return cType
|
|
|
|
def FillDat(lForce,configpath):
|
|
|
|
if not configpath:
|
|
configpath= []
|
|
configpath.append(__file__[:-len('FromDucks.py')] + "FromDucks.dat")
|
|
configpath.append(__file__[:-len('FromDucks.py')] + "Characters.dat")
|
|
configpath.append(__file__[:-len('FromDucks.py')] + "Languages.dat")
|
|
|
|
if lForce:
|
|
fd = ProgressBarDialog(3, "Rebuilding")
|
|
fd.Show(ComicRack.MainWindow)
|
|
#progressDlg = Progress()
|
|
#progressDlg.CenterToParent()
|
|
#progressDlg.Show()
|
|
fd.Update("Reading/Rebuilding [DB]", 1, "Local Database ")
|
|
fd.Refresh()
|
|
|
|
for cycle in configpath:
|
|
|
|
if "FromDucks.dat" in cycle:
|
|
cWeb='https://coa.inducks.org/inducks/isv/inducks_publication.isv'
|
|
elif "Characters.dat" in cycle:
|
|
cWeb='https://coa.inducks.org/inducks/isv/inducks_charactername.isv'
|
|
elif "Languages.dat" in cycle:
|
|
cWeb='https://coa.inducks.org/inducks/isv/inducks_language.isv'
|
|
|
|
if lForce or not FileInfo(cycle).Exists:
|
|
|
|
try:
|
|
fileHandle = _read_url(cWeb)
|
|
if lForce:
|
|
fd.Update("Reading/Rebuilding [" + cWeb + "]", 1, "Local Database ")
|
|
fd.Refresh()
|
|
#progressDlg.modifyPrompt("Reading/Rebuilding [" + cWeb + "]")
|
|
|
|
#contents = fileHandle.readlines()
|
|
|
|
except IOError:
|
|
MessageBox.Show('Cannot open URL ' + cWeb + 'for reading')
|
|
sys.exit(0)
|
|
|
|
#fileHandle.close()
|
|
|
|
#fileHandle = open(cycle, 'w')
|
|
|
|
open(cycle, 'wb').write(fileHandle.encode("utf-8"))
|
|
|
|
#for line in contents:
|
|
# fileHandle.write(line)
|
|
|
|
#fileHandle.close()
|
|
|
|
elif not FileInfo(cycle).Exists:
|
|
|
|
MessageBox.Show('Cannot open ' + cycle + '\nPlease REBUILD it!')
|
|
sys.exit(0)
|
|
|
|
if lForce:
|
|
fd.Close()
|
|
#progressDlg.Close()
|
|
MessageBox.Show('REBUILD completed!')
|
|
|
|
#===============================================================================
|
|
# class Progress(Form):
|
|
#
|
|
# def __init__(self):
|
|
#
|
|
# self.ClientSize = Size(400, 100)
|
|
#
|
|
# self.label = Label()
|
|
# self.label.Text = ""
|
|
# self.label.Location = Point(10, 10)
|
|
# self.label.Height = 40
|
|
# self.label.Width = 400
|
|
# self.label.TextAlign = ContentAlignment.MiddleLeft
|
|
#
|
|
# self.Controls.Add(self.label)
|
|
# self.FormBorderStyle = FormBorderStyle.FixedDialog
|
|
# self.Name = "fromducks"
|
|
# self.StartPosition = FormStartPosition.CenterParent
|
|
# self.Text = "Data (C) The Inducks Team (http://inducks.org)"
|
|
# self.MinimizeBox = False
|
|
# self.MaximizeBox = False
|
|
# def modifyPrompt(self, newText):
|
|
# self.label.Text = newText
|
|
# self.Update()
|
|
#===============================================================================
|
|
|
|
def MonthNum(month):
|
|
|
|
dMonth={"Jan": 1, "Feb": 2, "Mar": 3 ,"Apr": 4,"May": 5,"Jun": 6,"Jul": 7,"Aug": 8,"Sep": 9,"Oct": 10,"Nov": 11,"Dec": 12}
|
|
if month[:3] in dMonth:
|
|
return dMonth[month[:3]]
|
|
else:
|
|
return 0
|
|
|
|
#===============================================================================
|
|
# class Stats(Form):
|
|
#
|
|
# def __init__(self):
|
|
#
|
|
# self.label = Label()
|
|
# self.label2 = Label()
|
|
#
|
|
# self.label.Location = Point(10, 10)
|
|
# self.label.Size = Size(200, 50)
|
|
# self.label.Name = "label1"
|
|
# self.label.Text = "Total Scraped: "
|
|
# self.label.TextAlign = ContentAlignment.MiddleLeft
|
|
#
|
|
# self.label2.Location = Point(10, 40)
|
|
# self.label2.Size = Size(250, 50)
|
|
# self.label2.Name = "label2"
|
|
# self.label2.Text = ""
|
|
# self.label2.TextAlign = ContentAlignment.MiddleLeft
|
|
#
|
|
# self.ClientSize = Size(300, 100)
|
|
# self.Controls.Add(self.label)
|
|
# self.Controls.Add(self.label2)
|
|
#
|
|
# self.FormBorderStyle = FormBorderStyle.FixedDialog
|
|
# self.Name = "Scrape"
|
|
# self.StartPosition = FormStartPosition.CenterParent
|
|
# self.Text = "Scraping from I.N.D.U.C.K.S."
|
|
# self.MinimizeBox = False
|
|
# self.MaximizeBox = False
|
|
#
|
|
# def modifyStats(self, nBook, TotBooks, cSeries, cNumber):
|
|
# self.label.Text = "Scraping... " + str(nBook) + " of " + str(TotBooks)
|
|
# self.label2.Text = cSeries + " n." + cNumber
|
|
# self.Update()
|
|
#
|
|
# def NotFound(self, text):
|
|
# self.label2.Text = text + " *** Not Found *** "
|
|
# self.Update()
|
|
#===============================================================================
|
|
|
|
def debuglog():
|
|
|
|
traceback = sys.exc_info()[2]
|
|
stackTrace = []
|
|
|
|
logfile = Path.Combine(__file__[:-len('FromDucks.py')] , "FromDucks_Debug_Log.txt")
|
|
|
|
if DEBUG:print "Writing Log to " + logfile
|
|
|
|
log = open(logfile, 'a')
|
|
try:
|
|
log.write (str(datetime.now().strftime("%A %d %B %Y %H:%M:%S")) + '\n')
|
|
log.write ("".join(['Caught ', sys.exc_info()[0].__name__, ': ',sstr(sys.exc_info()[1]), '\n']))
|
|
print 'Caught ', sys.exc_info()[0].__name__, ': ',sstr(sys.exc_info()[1])
|
|
except:
|
|
pass
|
|
while traceback is not None:
|
|
frame = traceback.tb_frame
|
|
lineno = traceback.tb_lineno
|
|
code = frame.f_code
|
|
filename = code.co_filename
|
|
name = code.co_name
|
|
stackTrace.append((filename, lineno, name))
|
|
traceback = traceback.tb_next
|
|
|
|
nL = 0
|
|
for line in stackTrace:
|
|
nL += 1
|
|
print nL,"-",line
|
|
log.write (",".join("%s" % tup for tup in line))
|
|
|
|
log.write ('\n')
|
|
log.flush()
|
|
log.close()
|
|
|
|
def sstr(object):
|
|
''' safely converts the given object into a string (sstr = safestr) '''
|
|
if object is None:
|
|
return '<None>'
|
|
if is_string(object):
|
|
# this is needed, because str() breaks on some strings that have unicode
|
|
# characters, due to a python bug. (all strings in python are unicode.)
|
|
return object
|
|
return str(object)
|
|
|
|
def log_BD(bdstr,bdstat,lTime):
|
|
|
|
bdlogfile = Path.Combine(__file__[:-len('FromDucks.py')] , "FromDucks_Rename_Log.txt")
|
|
|
|
bdlog = open(bdlogfile, 'a')
|
|
if lTime == 1:
|
|
cDT = str(datetime.now().strftime("%A %d %B %Y %H:%M:%S")) + " > "
|
|
|
|
else:
|
|
cDT= ""
|
|
|
|
bdlog.write (cDT.encode("utf-8") + bdstr.encode("utf-8") + " " + bdstat.encode("utf-8") + "\n")
|
|
|
|
bdlog.flush()
|
|
bdlog.close()
|
|
|
|
def is_string(object):
|
|
''' returns a boolean indicating whether the given object is a string '''
|
|
if object is None:
|
|
return False
|
|
return isinstance(object, basestring)
|
|
|
|
class ProgressBarDialog(Form):
|
|
|
|
def __init__(self, nMax, cText="Scraping Files"):
|
|
|
|
self.Text = cText #"Scraping Files"
|
|
self.Size = Size(350, 150)
|
|
self.StartPosition = FormStartPosition.CenterScreen
|
|
|
|
self.pb = ProgressBar()
|
|
self.traitement = Label()
|
|
|
|
self.traitement.Location = Point(20, 5)
|
|
self.traitement.Name = "scraping"
|
|
self.traitement.Size = Size(300, 50)
|
|
self.traitement.Text = ""
|
|
|
|
self.pb.Size = Size(300, 20)
|
|
self.pb.Location = Point(20, 50)
|
|
self.pb.Maximum = 100
|
|
self.pb.Minimum = 0
|
|
self.pb.Step = 100.00 / nMax
|
|
self.pb.Value = 0.00
|
|
self.pb.BackColor = Color.LightGreen
|
|
self.pb.Text = ""
|
|
self.pb.ForeColor = Color.Black
|
|
|
|
self.Controls.Add(self.pb)
|
|
self.Controls.Add(self.traitement)
|
|
|
|
def Update(self, cText, nInc, cHead="Scraping Files "):
|
|
self.traitement.Text = "\n" + cText
|
|
if nInc > 0:
|
|
self.Text = cHead + self.pb.Value.ToString() + "%"
|
|
self.pb.Increment(self.pb.Step)
|
|
|
|
def _read_url(url):
|
|
|
|
page = ''
|
|
|
|
requestUri = url
|
|
|
|
try:
|
|
Req = HttpWebRequest.Create(requestUri)
|
|
Req.Timeout = 60000
|
|
Req.UserAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
|
|
Req.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
|
|
|
|
#Req.Referer = requestUri
|
|
Req.Accept = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'
|
|
Req.Headers.Add('Accept-Language','en-US,en;q=0.9,it;q=0.8,fr;q=0.7,de-DE;q=0.6,de;q=0.5')
|
|
|
|
Req.KeepAlive = True
|
|
webresponse = Req.GetResponse()
|
|
a = webresponse.Cookies
|
|
|
|
inStream = webresponse.GetResponseStream()
|
|
encode = Encoding.GetEncoding("utf-8")
|
|
ReadStream = StreamReader(inStream, encode)
|
|
page = ReadStream.ReadToEnd()
|
|
|
|
except:
|
|
debuglog()
|
|
|
|
try:
|
|
inStream.Close()
|
|
webresponse.Close()
|
|
except:
|
|
pass
|
|
|
|
return page
|