emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Google calendar to org mode script and a feature request for agenda
@ 2010-06-29 22:28 Eric S Fraga
  2010-06-30  5:43 ` Stephen Eglen
  2010-07-07 20:38 ` Daniel Martins
  0 siblings, 2 replies; 7+ messages in thread
From: Eric S Fraga @ 2010-06-29 22:28 UTC (permalink / raw)
  To: org-mode mailing list

[-- Attachment #1: Type: text/plain, Size: 2495 bytes --]

Hello,

I finally got myself an Android phone (and am loving it, especially
with an "all you can eat" data plan :-).  I have tried mobileorg for
Android but it's obviously early days and it's actually not really
what I want.

However, I am very happy with the Google syncing provided by the
phone, both for email and for the calendar.  This has caused me to
revisit the possibility of a smoother integration between Google's
calendar and org-mode.

First, I have created an awk script (yes, I'm dating myself: I do use
awk in preference to perl et al.) which allows me to convert the iCal
export from Google calendar to a sequence of org headlines (see
attached).  It's a preliminary version and seems to translate what I
need: simple day and timed events, mostly those that I will tend to do
on the phone as opposed to when I'm at my computer.  I'm not trying
for a comprehensive translation program here...  but I'm putting it on
the list in case anybody finds it useful.

I use this script as follows:

   wget [address specified by google for my calendar]  --> basic.ics
   awk -f ical2org.awk < basic.ics >> googlecalendar.org

this appends any entries in my specific google calendar to the given
org file.  When I go the other way (creating an ics file from org), I
import the org items into a different calendar on google.  When
entries have been synced, I typically delete the original entries
placed in google to avoid them being downloaded over and over again
[1].

* A feature request: time prompt for insert diary agenda function

Anyway, my increased use of google's calendar, has highlighted a
short-coming (?) of the agenda view (or more strictly speaking, the
iCal exporter): entries in which the time of appointment, say, is on
the headline but the date is on the following line, say, get converted
to "day" events as opposed to day+time events.  I.e. something like

   * 11am meeting with colleages
     <2010-06-30 Wed>

does not get exported as a timed event.  Obviously, the easy solution
is to put the time in the date stamp.  However, I like using the
"insert diary" function in the agenda view for defining appointments
and this doesn't allow the time to be specified other than in a
headline.  Would it be possible to enhance the insert diary function
to prompt for a time (and while we're at it, tags as well)?

Thanks,
eric


Footnotes: 
[1]  it may be possible to use the unique ID for each event to avoid creating duplicates... something to look at in the future.


[-- Attachment #2: ical2org.awk --]
[-- Type: text/plain, Size: 2428 bytes --]

# awk script for converting an iCal formatted file to a sequence of org-mode headings.
# this may not work in general but seems to work for day and timed events from Google's
# calendar, which is really all I need right now...
#
# Eric S Fraga, 20100629

BEGIN {
  # use a colon to separate the type of data line from the actual contents
  FS = ":";
  entry = ""
  headline = ""
  id = ""
  indescription = 0;
}

# any line that starts at the left with a non-space character is a new data field

/^[A-Z]/ {indescription = 0;}

# this type of entry represents a day entry, not timed, with date stamp YYYYMMDD
/^DTSTART;VALUE=DATE/ {
  date = gensub("([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9]).*[\r]", "\\1-\\2-\\3", "g", $2)
  #print date
}

# this represents a timed entry with date and time stamp YYYYMMDDTHHMMSS
# we ignore the seconds

/^DTSTART:/ {
  #print $0
  date = gensub("([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])T([0-9][0-9])([0-9][0-9]).*[\r]", "\\1-\\2-\\3 \\4:\\5", "g", $2);
  # print date;
}

# The description will the contents of the entry in org-mode.
# this line may be continued and as I do not know if other lines may be continued,
# we only process continuation lines that come immediately after this one

/^DESCRIPTION/ { 
  entry = gensub("\r", "", "g", $2);
  indescription = 1;
}

# continuation lines (at least from Google) start with two spaces
# if the continuation is after a description, append the entry

/^  / { 
  # print "** continuation line: " $0
  if (indescription) {
    entry = entry gensub("\r", "", "g", $0);
  }
}

# the summary will be the org heading

/^SUMMARY/ { headline = gensub("(.*)[\r]", "\\1", "g", $2); }

# the unique ID will be stored as a property of the entry

/^UID/ { id = gensub("(.*)[\r]", "\\1", "g", $2); }

# when we reach the end of the event line, we output everything we
# have collected so far, creating a top level org headline with the
# date/time stamp, unique ID property and the contents, if any

/^END:VEVENT/ {
  print "* " headline
  print "  :PROPERTIES:"
  print "  :ID:       " id
  print "  :END:"
  print "  <" date ">"
  # for the entry, convert all embedded "\n" strings to actual newlines
  print ""
  print gensub("\\\\n", "\n", "g", entry); # need 4 backslash to get one in the pattern!
  headline = ""
  date = ""
  entry = ""
  indescription = 0
}

END {
    print strftime("* COMMENT ical2org finished at [%Y-%m-%d %H:%M]");
}

[-- Attachment #3: Type: text/plain, Size: 75 bytes --]

-- 
Eric S Fraga
GnuPG: 8F5C 279D 3907 E14A 5C29  570D C891 93D8 FFFC F67D

[-- Attachment #4: Type: text/plain, Size: 201 bytes --]

_______________________________________________
Emacs-orgmode mailing list
Please use `Reply All' to send replies to the list.
Emacs-orgmode@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-orgmode

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Google calendar to org mode script and a feature request for agenda
  2010-06-29 22:28 Google calendar to org mode script and a feature request for agenda Eric S Fraga
@ 2010-06-30  5:43 ` Stephen Eglen
  2010-06-30  8:14   ` Eric S Fraga
  2010-07-07 20:38 ` Daniel Martins
  1 sibling, 1 reply; 7+ messages in thread
From: Stephen Eglen @ 2010-06-30  5:43 UTC (permalink / raw)
  To: emacs-orgmode

>
> does not get exported as a timed event.  Obviously, the easy solution
> is to put the time in the date stamp.  However, I like using the
> "insert diary" function in the agenda view for defining appointments
> and this doesn't allow the time to be specified other than in a
> headline.  Would it be possible to enhance the insert diary function
> to prompt for a time (and while we're at it, tags as well)?

hi Eric, 
I had a similar request, and we worked out a solution to this a while
ago.  In the agenda, try 'i d', and then type something like
'11:00-11:45 Seminar with Bob', and the code should parse out the
timestamp as long as you have the following variable set to t:

(setq org-agenda-insert-diary-extract-time t)

Stephen

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Re: Google calendar to org mode script and a feature request for agenda
  2010-06-30  5:43 ` Stephen Eglen
@ 2010-06-30  8:14   ` Eric S Fraga
  0 siblings, 0 replies; 7+ messages in thread
From: Eric S Fraga @ 2010-06-30  8:14 UTC (permalink / raw)
  To: Stephen Eglen; +Cc: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 971 bytes --]

On Wed, 30 Jun 2010 06:43:38 +0100, Stephen Eglen <S.J.Eglen@damtp.cam.ac.uk> wrote:
> 
> >
> > does not get exported as a timed event.  Obviously, the easy solution
> > is to put the time in the date stamp.  However, I like using the
> > "insert diary" function in the agenda view for defining appointments
> > and this doesn't allow the time to be specified other than in a
> > headline.  Would it be possible to enhance the insert diary function
> > to prompt for a time (and while we're at it, tags as well)?
> 
> hi Eric, 
> I had a similar request, and we worked out a solution to this a while
> ago.  In the agenda, try 'i d', and then type something like
> '11:00-11:45 Seminar with Bob', and the code should parse out the
> timestamp as long as you have the following variable set to t:
> 
> (setq org-agenda-insert-diary-extract-time t)
> 
> Stephen

Indeed!  Exactly what I wanted.  I should have *known* that org would
already have what I want.

Thanks,
eric

[-- Attachment #2: Type: text/plain, Size: 75 bytes --]

-- 
Eric S Fraga
GnuPG: 8F5C 279D 3907 E14A 5C29  570D C891 93D8 FFFC F67D

[-- Attachment #3: Type: text/plain, Size: 201 bytes --]

_______________________________________________
Emacs-orgmode mailing list
Please use `Reply All' to send replies to the list.
Emacs-orgmode@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-orgmode

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Google calendar to org mode script and a feature request for agenda
  2010-06-29 22:28 Google calendar to org mode script and a feature request for agenda Eric S Fraga
  2010-06-30  5:43 ` Stephen Eglen
@ 2010-07-07 20:38 ` Daniel Martins
  2010-07-07 22:17   ` Eric S Fraga
  2010-07-08 18:07   ` Eric S Fraga
  1 sibling, 2 replies; 7+ messages in thread
From: Daniel Martins @ 2010-07-07 20:38 UTC (permalink / raw)
  To: Eric S Fraga; +Cc: org-mode mailing list

Eric,

Your awk seems to get timed appts in GMT

How can I adapt it to GMT-3

Daniel

2010/6/29 Eric S Fraga <ucecesf@ucl.ac.uk>:
> Hello,
>
> I finally got myself an Android phone (and am loving it, especially
> with an "all you can eat" data plan :-).  I have tried mobileorg for
> Android but it's obviously early days and it's actually not really
> what I want.
>
> However, I am very happy with the Google syncing provided by the
> phone, both for email and for the calendar.  This has caused me to
> revisit the possibility of a smoother integration between Google's
> calendar and org-mode.
>
> First, I have created an awk script (yes, I'm dating myself: I do use
> awk in preference to perl et al.) which allows me to convert the iCal
> export from Google calendar to a sequence of org headlines (see
> attached).  It's a preliminary version and seems to translate what I
> need: simple day and timed events, mostly those that I will tend to do
> on the phone as opposed to when I'm at my computer.  I'm not trying
> for a comprehensive translation program here...  but I'm putting it on
> the list in case anybody finds it useful.
>
> I use this script as follows:
>
>   wget [address specified by google for my calendar]  --> basic.ics
>   awk -f ical2org.awk < basic.ics >> googlecalendar.org
>
> this appends any entries in my specific google calendar to the given
> org file.  When I go the other way (creating an ics file from org), I
> import the org items into a different calendar on google.  When
> entries have been synced, I typically delete the original entries
> placed in google to avoid them being downloaded over and over again
> [1].
>
> * A feature request: time prompt for insert diary agenda function
>
> Anyway, my increased use of google's calendar, has highlighted a
> short-coming (?) of the agenda view (or more strictly speaking, the
> iCal exporter): entries in which the time of appointment, say, is on
> the headline but the date is on the following line, say, get converted
> to "day" events as opposed to day+time events.  I.e. something like
>
>   * 11am meeting with colleages
>     <2010-06-30 Wed>
>
> does not get exported as a timed event.  Obviously, the easy solution
> is to put the time in the date stamp.  However, I like using the
> "insert diary" function in the agenda view for defining appointments
> and this doesn't allow the time to be specified other than in a
> headline.  Would it be possible to enhance the insert diary function
> to prompt for a time (and while we're at it, tags as well)?
>
> Thanks,
> eric
>
>
> Footnotes:
> [1]  it may be possible to use the unique ID for each event to avoid creating duplicates... something to look at in the future.
>
>
> --
> Eric S Fraga
> GnuPG: 8F5C 279D 3907 E14A 5C29  570D C891 93D8 FFFC F67D
>
> _______________________________________________
> Emacs-orgmode mailing list
> Please use `Reply All' to send replies to the list.
> Emacs-orgmode@gnu.org
> http://lists.gnu.org/mailman/listinfo/emacs-orgmode
>
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Google calendar to org mode script and a feature request for agenda
  2010-07-07 20:38 ` Daniel Martins
@ 2010-07-07 22:17   ` Eric S Fraga
  2010-07-07 22:57     ` Daniel Martins
  2010-07-08 18:07   ` Eric S Fraga
  1 sibling, 1 reply; 7+ messages in thread
From: Eric S Fraga @ 2010-07-07 22:17 UTC (permalink / raw)
  To: Daniel Martins; +Cc: org-mode mailing list

[-- Attachment #1: Type: text/plain, Size: 784 bytes --]

On Wed, 7 Jul 2010 17:38:45 -0300, Daniel Martins <danielemc@gmail.com> wrote:
> 
> Eric,
> 
> Your awk seems to get timed appts in GMT
> 
> How can I adapt it to GMT-3
> 
> Daniel

Daniel,

yes, thanks for pointing this out. The script indeed does not
translate the times to the local time zone.  Google outputs (in the
basic.ics file) times in GMT.  However, it also includes the time zone
information but my awk script ignores that information.  The script
also ignores the end time for timed events.

Obviously time for a v2 of this script!

let me have a think about this and I'll see if I can do something a
bit more intelligent (at least for Linux systems where possibly
compatible time zone information can be found in /usr/share/zoninfo/*)
and fix up the end times as well.


[-- Attachment #2: Type: text/plain, Size: 75 bytes --]

-- 
Eric S Fraga
GnuPG: 8F5C 279D 3907 E14A 5C29  570D C891 93D8 FFFC F67D

[-- Attachment #3: Type: text/plain, Size: 201 bytes --]

_______________________________________________
Emacs-orgmode mailing list
Please use `Reply All' to send replies to the list.
Emacs-orgmode@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-orgmode

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Google calendar to org mode script and a feature request for agenda
  2010-07-07 22:17   ` Eric S Fraga
@ 2010-07-07 22:57     ` Daniel Martins
  0 siblings, 0 replies; 7+ messages in thread
From: Daniel Martins @ 2010-07-07 22:57 UTC (permalink / raw)
  To: Eric S Fraga; +Cc: org-mode mailing list

OK Eric

Thank you!

Linux solution is fine!

I think we share the same "addiction" at moment.

Linux-Emacs-OrgMode-Android  and due to Android the need of Google
calendar syncing!

I tried using

gcaldaemon (there is a .deb file in

http://blog.philippheckel.com/2008/09/30/gcaldaemon-deb-package-for-ubuntu-kubuntu/

)

The org -> ics -> google calendar  works with some minor problem, but
I am not satisfied.

A simpler solution seems to be better

Daniel

PS When I saw GoogleCL I had some hope for a "final solution" of this problem

2010/7/7 Eric S Fraga <ucecesf@ucl.ac.uk>:
> On Wed, 7 Jul 2010 17:38:45 -0300, Daniel Martins <danielemc@gmail.com> wrote:
>>
>> Eric,
>>
>> Your awk seems to get timed appts in GMT
>>
>> How can I adapt it to GMT-3
>>
>> Daniel
>
> Daniel,
>
> yes, thanks for pointing this out. The script indeed does not
> translate the times to the local time zone.  Google outputs (in the
> basic.ics file) times in GMT.  However, it also includes the time zone
> information but my awk script ignores that information.  The script
> also ignores the end time for timed events.
>
> Obviously time for a v2 of this script!
>
> let me have a think about this and I'll see if I can do something a
> bit more intelligent (at least for Linux systems where possibly
> compatible time zone information can be found in /usr/share/zoninfo/*)
> and fix up the end times as well.
>
>
> --
> Eric S Fraga
> GnuPG: 8F5C 279D 3907 E14A 5C29  570D C891 93D8 FFFC F67D
>
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Google calendar to org mode script and a feature request for agenda
  2010-07-07 20:38 ` Daniel Martins
  2010-07-07 22:17   ` Eric S Fraga
@ 2010-07-08 18:07   ` Eric S Fraga
  1 sibling, 0 replies; 7+ messages in thread
From: Eric S Fraga @ 2010-07-08 18:07 UTC (permalink / raw)
  To: Daniel Martins; +Cc: org-mode mailing list

[-- Attachment #1: Type: text/plain, Size: 1435 bytes --]

On Wed, 7 Jul 2010 17:38:45 -0300, Daniel Martins <danielemc@gmail.com> wrote:
> 
> Eric,
> 
> Your awk seems to get timed appts in GMT
> 
> How can I adapt it to GMT-3
> 
> Daniel

Okay!  I think I've got this working for any time zone (as well as
adding some more functionality -- read the prologue in the script for
info).  

Attached is the awk script.  I use this from within a shell script (on
Linux) that essentially does this:

--8<---------------cut here---------------start------------->8---
ICS=basic.ics
ORG=googlecalendar.org
AWK=ical2org.awk

# get the Google calendar
wget  http://www.google.com/calendar/ical/[...]/basic.ics

# convert the ical entries to org format, adjusting for the
# time zone information

# this next command yields hours from UTC, + or -, times 100
# Note: this does not cater for those people living in time zones
# that are not aligned with discrete hours (e.g. Newfoundland)...
timezone=$(date +%z | sed 's/^\([+-]\)0/\1/')

# convert this to seconds for use in the awk script
seconds=$(($timezone*36))

# and now process the ics file with appropriate time zone
awk -f $AWK --assign SECONDS=$seconds < $ICS > $ORG
--8<---------------cut here---------------end--------------->8---

Please test this all out and let me know if it works.  If the date and
sed commands work, you should be adjusting the times by -3*3600=-10800
seconds.  This seems to be working for me with BST (aka GMT+1).

eric

[-- Attachment #2: ical2org.awk --]
[-- Type: text/plain, Size: 5496 bytes --]

# awk script for converting an iCal formatted file to a sequence of org-mode headings.
# this may not work in general but seems to work for day and timed events from Google's
# calendar, which is really all I need right now...
#
# usage:
#   awk -f THISFILE --assign SECONDS=SSSS < icalinputfile.ics > orgmodeentries.org
#
# where "SSSS" is the number of seconds to adjust time to take into
# account the local time zone relative to UTC (e.g. GMT+1 == 3600,
# GMT-1 == -3600).  I have not tested edge effects, specifically what
# happens when UTC time is a different day to local time and
# especially when an event with a duration crosses midnight in UTC
# time.  It should work but...
#
# Note: change org meta information generated below for author and
# email entries!
#
# Known bugs:
# - if the iCal entry has an event reminder, the description field in
#   the VALARM entry for the event will supercede the description field
#   of the originating entry.
# - not so much a bug as a possible assumption: date entries with no time
#   specified are assumed to be independent of the time zone.
#
# Eric S Fraga
# 20100629 - initial version
# 20100708 - added end times to timed events
#          - adjust times according to time zone information
#          - fixed incorrect transfer for entries with ":" embedded within the text
#          - added support for multi-line summary entries (which become headlines)
#----------------------------------------------------------------------------------

# a function to take the iCal formatted date+time, converted it into
# an internal form (seconds since time 0), and adjust according to the
# local time zone (specified by +-SECONDS on the argument to awk)

function datetimestamp(input)
{
    # convert the iCal Date+Time entry to a format that mktime can understand
    datespec = gensub("([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])T([0-9][0-9])([0-9][0-9])([0-9][0-9]).*[\r]*", "\\1 \\2 \\3 \\4 \\5 \\6", "g", input);
    # print "date spec   : " datespec;
    # convert this date+time into seconds from the beginning of time
    timestamp = mktime(datespec);
    # print "time stamp  : " timestamp;
    # and adjust for the time zone, number of seconds from GMT/UTC.
    timestamp += SECONDS;
    # print "adjusted    : " timestamp
    # print "Time stamp  : " strftime("%Y-%m-%d %H:%M", timestamp);
    return timestamp;
}

BEGIN {
    # use a colon to separate the type of data line from the actual contents
    FS = ":";
    date = "";
    time2given = 0;
    entry = ""
    icalentry = ""  # the full entry for inspection
    headline = ""
    id = ""
    indescription = 0;
    print "#+TITLE:     Main Google calendar entries"
    print "#+AUTHOR:    Eric S Fraga"
    print "#+EMAIL:     e.fraga@ucl.ac.uk"
    print "#+DESCRIPTION: converted using the ical2org awk script"
    print "#+CATEGORY: google"
    print " "
}

# any line that starts at the left with a non-space character is a new data field

/^[A-Z]/ {
    if (! index("DTSTAMP", $1)) icalentry = icalentry "\n" $0
    # this line terminates the collection of description and summary entries
    indescription = 0;
    insummary = 0;
}

# this type of entry represents a day entry, not timed, with date stamp YYYYMMDD

/^DTSTART;VALUE=DATE/ {
    date = gensub("([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9]).*[\r]", "\\1-\\2-\\3", "g", $2)
    # print date
}

# this represents a timed entry with date and time stamp YYYYMMDDTHHMMSS
# we ignore the seconds

/^DTSTART:/ {
    # print $0
    date = strftime("%Y-%m-%d %H:%M", datetimestamp($2));
    # print date;
}

# and the same for the end date; here we extract only the time and append this to the 
# date+time found by the DTSTART entry.  We assume that entry was there, of course.
# should probably add some error checking here!  In time...

/^DTEND:/ {
    # print $0
    time2 = strftime("%H:%M", datetimestamp($2));
    date = date "-" time2;
}

# The description will the contents of the entry in org-mode.
# this line may be continued.

/^DESCRIPTION/ { 
    $1 = "";
    entry = gensub("\r", "", "g", $0);
    indescription = 1;
}

# continuation lines (at least from Google) start with two spaces
# if the continuation is after a description or a summary, append the entry
# to the respective variable

/^  / { 
    # print "** continuation line: " $0
    if (indescription) {
	entry = entry gensub("\r", "", "g", $0);
    } else if (insummary) {
	summary = summary gensub("\r", "", "g", $0)
    }
    icalentry = icalentry "\n" $0
}

# the summary will be the org heading

/^SUMMARY/ { 
    $1 = "";
    summary = gensub("\r", "", "g", $0);
    insummary = 1;
}

# the unique ID will be stored as a property of the entry

/^UID/ { 
    $1 = "";
    id = gensub("\r", "", "g", $0);
}

# when we reach the end of the event line, we output everything we
# have collected so far, creating a top level org headline with the
# date/time stamp, unique ID property and the contents, if any

/^END:VEVENT/ {
    print "* " gensub ("\\\\n", " ", "g", summary)
    print "  :PROPERTIES:"
    print "  :ID:       " id
    print "  :END:"
    print "  <" date ">"
    # for the entry, convert all embedded "\n" strings to actual newlines
    print ""
    print gensub("\\\\n", "\n", "g", entry); # need 4 backslash to get one in the pattern!
    print "** COMMENT original iCal entry"
    print gensub("\r", "", "g", icalentry)
    summary = ""
    date = ""
    entry = ""
    icalentry = ""
    indescription = 0
}

[-- Attachment #3: Type: text/plain, Size: 75 bytes --]

-- 
Eric S Fraga
GnuPG: 8F5C 279D 3907 E14A 5C29  570D C891 93D8 FFFC F67D

[-- Attachment #4: Type: text/plain, Size: 201 bytes --]

_______________________________________________
Emacs-orgmode mailing list
Please use `Reply All' to send replies to the list.
Emacs-orgmode@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-orgmode

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2010-07-08 20:17 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-29 22:28 Google calendar to org mode script and a feature request for agenda Eric S Fraga
2010-06-30  5:43 ` Stephen Eglen
2010-06-30  8:14   ` Eric S Fraga
2010-07-07 20:38 ` Daniel Martins
2010-07-07 22:17   ` Eric S Fraga
2010-07-07 22:57     ` Daniel Martins
2010-07-08 18:07   ` Eric S Fraga

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).