Hi, y’all!
I’m not exactly “new” to Applescript, but I’ve only recently started trying to make it jump through hoops. Frankly I never had a need for it until this project. I’ve done some work with HyperCard and SuperCard in the past, but I’m really not that great a programmer. I found this forum via Google and am hoping y’all can help. I’m stumped!
I’m trying to put together a script that will automatically pull obituary, wedding, and engagement announcements from an archive and post them on a website. The script would seem to be pretty straightforward, but I’m having trouble with it. There’s a bug in it that causes the announcements to be copied in repeatedly. I can’t figure out why. I have this terrible feeling that my algorithm is flawed. So far I’ve only coded for the obits – since that’s not working right, I see no reason to get the other announcements working yet. The archive files are expected to be either Quark 4.1 files or plain text.
The process SHOULD be this: Find the correct archive folders on the server, get the announcements using a filename flag, open the announcement to extract the text, format the text into a HTML file, then upload that file to the server.
One problem may be platform related. The files (and script) are created under OS 9, but our server is running OS X. It doesn’t seem to matter if I run the script on 9 or X, though, the same problem occurs.
You can see the output of the script at http://www.heraldindependent.com/html/obits.html.
Here’s the actual script. I’ve pulled out the part that sends the files to the server for security. I mostly want to fix the bug, but if anybody sees another improvement please let me know. The whole thing isn’t appearing when I preview this message, I hope y’all get the full script.
-- This script gets obits from the archive files and pastes them into the appropriate master web page in HTML format. ******
-- First initialize some variables
set theDate to the current date -- this is the current date
set theText to ""
-- *********** This section of the code establishes file paths and gets the header and footer data *******************
-- Set up various variables
set folderPath to "WinVault:News Copy: CURRENT ISSUE PAGES:PAGES PRINTED" -- This sets the directory for the pages.
set workFilePath to "Data:The Herald Independent:" -- File path for local work files
set theFolders to recentPaperDates() -- Gets a list of folders to look in for announcements
set theTopFile to workFilePath & "stdtop.txt" -- Page header
set theBotFile to workFilePath & "stdbot.txt" -- Page footer
set theObitFile to workFilePath & "obits.html" -- Obits file
set theEngFile to workFilePath & "engagements.html" -- Engagements file
set theWedFile to workFilePath & "weddings.html" -- Weddings file
-- Get the file text into variables
open for access alias theTopFile --Open the top page template
set theTopText to (read alias theTopFile as text from 1 to (get eof alias theTopFile)) -- read the file into a variable
close access alias theTopFile -- Close the top page template
open for access alias theBotFile -- Open the bottom page template
set theBotText to (read alias theBotFile as text from 1 to (get eof alias theBotFile)) -- read the file into a variable
close access alias theBotFile -- close the bottom page template
-- ********** This section creates the obits file ********************************************************
set obitHeader to "<CENTER><H1>Obituaries</H1></CENTER><P><HR><P>" -- create Obits heading
set engHeader to "<CENTER><H1>Engagements</H1></CENTER><P><HR><P>" -- create Engagements heading
set wedHeader to "<CENTER><H1>Weddings</H1></CENTER><P><HR><P>" -- create Weddings heading
set theObits to obitHeader & getAnnouncements(theFolders, "obit", folderPath) -- assemble the obits into one variable
set theEng to engHeader & getAnnouncements(theFolders, "eng", folderPath) -- assemble the engagements into one variable
set theWed to wedHeader & getAnnouncements(theFolders, "wed", folderPath) -- assemble the weddings into one variable
copy theObits & return & "<hr>" & return & "Last Update: " & theDate & " - " & (current date) & "<P>" & return & return to theObitCode -- Add a "last updated" date stamp to the obits
copy theEng & return & "<hr>" & return & "Last Update: " & theDate & " - " & (current date) & "<P>" & return & return to theEngCode -- Add a "last updated" date stamp to the engagements
copy theWed & return & "<hr>" & return & "Last Update: " & theDate & " - " & (current date) & "<P>" & return & return to theWedCode -- Add a "last updated" date stamp to the weddings
set theNewCode to theTopText & return & theObitCode & return & theBotText -- Assemble the three pieces into a new variable
tell application "Finder"
if (exists file theObitFile) then delete file theObitFile -- Erase the old file
end tell
--Write the new code to the obit file
tell application "Finder" to make file at workFilePath with properties {name:"obits.html", creator type:"ttxt", file type:"TEXT"}
open for access alias theObitFile with write permission -- create the file
write theNewCode to alias theObitFile -- write to the file
close access alias theObitFile -- close the file
-- Now send the obits file to the Web server. Deleted for security reasons.
-- The above section will need to be rewritten to update the weddings and engagements, too
-- Classifieds use a different file structure so they'll need their own script.
-- ********** This section of the script defines our function handlers ****************************************
on getAnnouncements(theFolders, announceKey, folderPath)
-- This function extracts the text from Quark and text files and assembles it into one big text chunk.
-- Parameters:
-- theFolders - A list of the folders containing the announcements we want to run
-- announceKey - The keyword in the filename for the announcement type
-- folderPath - The path to the files
-- Initialize some variables
set returnValue to "" -- the return variable
set theText to "" -- holds the announcements
set theCode to "" -- holds the announcements after they've been formatted in HTML
repeat with thePaper from 1 to (the number of words in theFolders) -- step through the paper dates
-- Drill down to the " Gone Copy" folder. This expects a specific file structure and will fail if the structure is changed.
copy folderPath & ":" & PaperYear(word thePaper of theFolders) & ":" & (word thePaper of theFolders) & ": gone copy" to announceFolderPath
-- put the names of all the files in the "gone copy" folder into a variable
copy (list folder announceFolderPath) to fileList
repeat with theItem from 1 to (the number of items in fileList) --this repeat checks to see if we've got an announcement of the correct type
set currentFile to announceFolderPath & ":" & (item theItem of fileList) -- assemble the file path
if currentFile contains announceKey then -- yep, it's an announcement of the correct type
tell application "Finder"
set fileType to (file type of file currentFile) -- get the file type
end tell
if fileType is "XDOC" then -- it's a Quark file
tell application "QuarkXPressâ„¢" -- this tell will extract the text of the obit
activate
open file (announceFolderPath & ":" & (item theItem of fileList)) -- open this particular announcement
try -- it probably doesn't need to be this complicated but I copied this block from someone else's script
repeat with theStory from 1 to count of stories in document 1
if exists word 1 of story theStory of document 1 then
copy the text of story theStory of document 1 to theText -- dump the text into a variable
end if
end repeat
on error errMsg number errnum
-- need to beware of problems here (disk full, ???)
display dialog (errMsg & return & return & errnum) buttons {"Oops!"} default button 1 with icon 0
return
end try
close document 1 -- close the obit file
end tell -- end of getting a Quark file
else -- it's not a Quark file, so...
if fileType is "TEXT" then -- it's a text file
open for access file currentFile -- open the file
set theText to (read file currentFile as text from 1 to (get eof file currentFile))
close access file currentFile
else -- Error! It's neither Quark or text!
set theText to ""
end if --end of getting a text file
end if -- end of the file type check
-- Now format the text in HTML in a new variable theCode, which only means adding "<P>" tags at the graph breaks
repeat with theGraph from 1 to (the number of paragraphs in theText)
copy theCode & (paragraph theGraph of theText) & "<P>" & return to theCode
end repeat
copy (theCode & return & "<HR>" & return) to theCode -- get all the announcements together with a standard separator between them
end if -- end of the check for the announcement keyword check
end repeat -- end of stepping through the file list
copy returnValue & theCode to returnValue -- Now put the announcement at the end of any previous announcements
end repeat -- end of stepping through the paper dates
return returnValue -- sends the announcement text chunk
end getAnnouncements
on recentPaperDates()
-- this handler figures out the dates of the last month of papers
--and returns them in a list.
-- initialize some empty global variables
global gPaperList
copy "" to gPaperList
-- Get the date range
global gTodaysDate
set gTodaysDate to the current date -- today
global gStartDate
set gStartDate to (the (current date) - (14 * days)) -- subtract one week
-- Extract the paper dates
set gTheDate to gStartDate -- initialize our counter
repeat while gTheDate ≠gTodaysDate
if the weekday of gTheDate is Tuesday then -- it's Tuesday
set gPaperList to (gPaperList & numberDate(gTheDate) & ", ") -- add this date to the paper list
else
if the weekday of gTheDate is Friday then -- it's Friday
set gPaperList to (gPaperList & numberDate(gTheDate) & ", ") --add this date to the paper list
end if
end if
set gTheDate to (gTheDate + (1 * days)) -- increment the counter
end repeat
return gPaperList
end recentPaperDates
on numberDate(theDate)
-- this little function converts the date to the six-digit number used in the HI archive
--get the month into numerical format (@#$% applescript!)
if the month of theDate is January then set theMonth to "01" as string
if the month of theDate is February then set theMonth to "02" as string
if the month of theDate is March then set theMonth to "03" as string
if the month of theDate is April then set theMonth to "04" as string
if the month of theDate is May then set theMonth to "05" as string
if the month of theDate is June then set theMonth to "06 as string"
if the month of theDate is July then set theMonth to "07" as string
if the month of theDate is August then set theMonth to "08" as string
if the month of theDate is September then set theMonth to "09" as string
if the month of theDate is October then set theMonth to "10" as string
if the month of theDate is November then set theMonth to "11" as string
if the month of theDate is December then set theMonth to "12" as string
set theDay to (the day of theDate as string) -- get the day into a two-digit number as a string
if the number of characters in theDay < 2 then set theDay to "0" & theDay
set theyear to (characters 3 thru 4 of (the year of theDate as string)) -- extract the year
set theReturnValue to theMonth & theDay & theyear
return theReturnValue
end numberDate
on PaperYear(theFolderName)
-- this function extracts the year from the six-digit flder name
set theyear to "20" & (characters 5 thru 6 of theFolderName)
return theyear
end PaperYear
on updateObitCode(theObitCode, theObitPage)
-- this function assembles the code from the HTML file
open for access theObitPage with write permission
set theText to (read alias theObitPage as text from 1 to (get eof alias theObitPage)) as text
-- Step through the lines of the file looking for the trigger lines
repeat with theLine from 1 to (the words of theText)
if line theLine of theText contains "StartScriptSource" then
copy theLine to topCodeLineDiv -- identifies the bottom of the top
end if
if line theLine of theText contains "EndScriptSource" then
copy theLine to botCodeLineDiv -- identifies the top of the bottom
end if
end repeat
-- Now actually separate stuff into three variables
repeat with theLine from 1 to (the words of theCode) -- actually do the separation
if theLine ≤ topCodeLineDiv then -- we're still in the top part of the file
copy theTopCode & (line theLine of theCode) & " " to theTopCode
end if
if (theLine > topCodeLineDiv) and (theLine < botCodeLineDiv) then
-- we're in the part that will change
next
end if
if theLine ≥ botCodeLineDiv then -- we're now in the bottom part of the file
copy theBotCode & (line theLine of theCode) & " " to theBotCode
end if
end repeat
-- Now reassemble the three variables into a single block of HTML code
copy theTopCode & return & theObitCode & return & theBotCode to theNewCode
write theNewCode to alias theObitPage as text
close access alias theObitPage
return "true"
end updateObitCode
Model: Power Mac G4
AppleScript: 1.8.3
Browser: Netscape/7.02
Operating System: Mac OS 9.2.x