Giter VIP home page Giter VIP logo

go-calendar's Introduction

GO Calendar

Lint Generate Calendars Deploy Site Automated Release GitHub all releases

An automated unofficial iCal calendar generator for Pokémon GO events powered by Leek Duck, so you can easily have a Pokémon GO calendar on your phone (iOS & Android) or computer (Linux, macOS & Windows) that is always up-to-date.

Take a look at the website to get setup with the calendar.

Sources & Credit

All events are sourced from Leek Duck via bigfoott/ScrapedDuck, using the events JSON resource.

This project just aims to take all that brilliant hard work and dedication from the Leek Duck team, that is presented oh-so nicely on the Leek Duck website, and create a highly convenient and easily consumable auto-updating iCal calendar for use in any modern calendar client.

Development

Project is just a simple PHP CLI script using a few Symfony libraries for the sake of convenience, not the best and far from optimal, but fast and easy to maintain. The idea is to just have it get executed every 24 hours by a GitHub Action workflow, in which it updates the output fragment of ./dist/gocal.ics and commits it back to the main repo branch. This keeps the URL consistent so in theory calendar clients should be able to subscribe to it.

There is a makefile in the root of the project that does most of the heavy lifting. A brief overview of the current makefile:

# Build the relevant Docker containers for the project
make build

# Bring up/define in waiting the Docker containers for the project in detached mode
make up

# Tear down the running containers
make down

# Tear down and bring back up the containers for the project, shortcut for:
# $ make down && make up
make restart

# Install the project dependencies via the project container
make install

# Lint the projects code via the project container
make lint

# Generate the calendar file into dist/gocal.ics via the project container
make gen

# Build the pages site into a static HTML file in pages/dist
make site

# Generate the calendar then build the pages site
make all

As for the code itself, bin/gocal is the entrypoint of this CLI tool. It will bootstrap the Symfony console library and pull in the instructed commands from src/Commands.

Hopefully the code should be clear enough to be self documenting, although I'm not usually one to rely on such things alone, given the relative size of the project and associated debug output lines enclosing code blocks, it should be fine in this circumstance. If the project grows any larger, then I'll produce the appropriate documentation to support it.

A note on time zones and local time

This was a pain in the arse to solve, and I went through a lot of iterations coming up with a working solution. I had to get my hands dirty and go digging, looking at the generated date output formats in the iCal file and delve into the Spatie iCal library source to figure out what it was doing that it shouldn't be.

The first clue was in the generated dates in the output iCal file, any start and end dates that also had times were suffixed with a Z. According to this SO post, any start and end dates with times that end with Z will be interpreted in a UTC timezone, regardless of the timezone - or lack thereof - in the calendar or event.

Next step, we need to remove the Z by finding out where and how its being added.

Turns out in \Spatie\IcalendarGenerator\Properties\DateTimeProperty::getValue if the DateTime entity passed is in UTC (which is the default in PHP if no time zone is specified when creating a DateTime entity), regardless of the state of withoutTimezone(), getValue will append Z to the generated DateTimeValue as its only checks are if the DateTime is in UTC and has a time associated with it. The calendar clients will then interpret this as a set UTC time zone when in fact we didn't want that as we provided no initial time zone and removed time zones with withoutTimezone(). The Spatie documentation for spatie/icalendar-generator doesn't specify this behaviour, and I believe this to be a bug in the library... kinda. More on that below as I worked on a potential PR only to hit a gotcha scenario.

To illustrate the issue, this is the current code:

public function getValue(): string
{
    return $this->isUTC() && $this->dateTimeValue->hasTime()
        ? "{$this->dateTimeValue->format()}Z"
        : $this->dateTimeValue->format();
}

... and this is what I think it should be:

// Expose the existing $withoutTimeZone parameter captured in the __construct as a class property
private bool $withoutTimeZone;

public function getValue(): string
{
    return $this->isUTC() && $this->dateTimeValue->hasTime() && ! $this->withoutTimeZone
        ? "{$this->dateTimeValue->format()}Z"
        : $this->dateTimeValue->format();
}

This as we should only be adding the Z suffix if the time zone has been explicitly set, otherwise we are getting the UTC time zone set and thus interpreted by default, which is not intended if you've specified withoutTimeZone() on DateTime's initialised with no time zone, thus defaulting to UTC.

The workaround being to simply set a random time zone on the DateTime being created and then use withoutTimeZone(), as it will correctly strip out/not generate any time zone related properties making all dates interpret as intended - local time.

Now, back to that kinda, that lovely gotcha. I've had a go at patching this bug and submitting a PR for it, and now I see their problem, and it doesn't really have a clean solution. UTC DateTime's are used for internal time zone calculations, mainly for setting boundaries to expected time zone shifts, such as during summer. Patching it with the above fix solves the issues with implicit/default UTC usage and withoutTimeZone() used in combination, but breaks all DTSTAMP generation which needs to be UTC based. This is as internally they are using withoutTimeZone() to ensure that all user defined time zones are stripped from these internal DateTime's, to normalise them onto a UTC base, as is required for fixed points in time such as time zone boundaries. Its not an easy solve without some major reworking of how dates are safely handled for time zone boundaries in the library.

For now, I'm going to leave my hack in this repo. Setting the time zone to GMT on the event dates in combination with using withoutTimeZone() allows the library to skip the UTC logic, giving the desired effect of local times on the events due to the UTC Z suffix and all time zone stuff being dropped from the generated iCal file. I'll maybe submit a PR just with a documentation change to alert other future users of the library to this gotcha scenario, although I need to find a good way of phrasing it before I do so, as the above is a bit of a brain-teaser.

Legal

All rights reserved by their respective owners.

This project is not officially affiliated with Pokémon GO and is intended to fall under Fair Use doctrine, similar to any other informational site such as a wiki.

Pokémon and its trademarks are ©1995-2022 Nintendo, Creatures, and GAMEFREAK.

All images and names owned and trademarked by Nintendo, Niantic, The Pokémon Company, and GAMEFREAK are property of their respective owners.

go-calendar's People

Contributors

othyn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

go-calendar's Issues

Missing download links for event type calendars

The release workflow needs to dynamically load the relative file paths what files it should attach to the release, as this cannot be a fixed list for the same reasons as with the static site generator - if Leek Duck add a new event type, the calendar generation will automatically handle it, but it needs to be automatically refected in static resources such as the website and the releases to avoid the project going stale from requiring manual intervention.

The static site got around that, now need to also tackle the release action. Thinking of adding the dynamic asset file path to the dist/manifest.json as a new key, so no processing is required in the action as its just a straight list of generated calendar paths, and reading that out with a step, then passing the paths variable into the release files: key.

Great project

I don't have an issue to report, but think this is a great project. I created something similar via iOS shortcuts. Thanks for putting together something a bit more automated :D

Access past events

Description

Is it possible to compile another set of files to include events from the past? I would like to access all events, not just future and ongoig ones.

Desired Behavior

I am creating a dedicated calendar app for Android. It would be good if it could act like an archive too.

Additional Context

No response

Future events missing in calendar

Description

Looking at the Calendar on my phone, as well as on my desktop in Outlook, I don't see upcoming events farther in the future.

I see Goomy and Cynaquil CD days in the future, but no spotlight hour or raid hour.

Typically I would assume user error, and that the files were not properly imported, resulting in not getting new data.
I however have not touched anything related to this in many months.

I don't know what distance into the future it is designed to load, and if the user has control of that, but it seems weird and thought I would bring it up.

I see spotlight hour for today, and raid hour for tomorrow, and I am curious to see if the next set appears after one is done.
The fact that I am pretty sure this has been working properly for awhile (I think?) and now isn't loading things in the ICS files, just makes me wonder. Has there been changes?

Version

Unknown

Steps to Reproduce

Look on phone or outlook.

Screenshots

No response

Device

Samsung S23

Operating System

Android 14

Additional Context

No response

Mobile Friendly / More space efficient

Description

Right now calendar events show up as [Raid Hour] Mon Raid Hour.
There is a lot of repetition and it wastes space on calendars.

Desired Behavior

It would be great if there would be a "mobile" version or a "short" version of the calendars that would remove one of these references.

Even having [CD] [RH], etc would be a significant improvement.
Although ss the individual calendars can have unique colors, it already will can have a unique identifier and I don't even see a need for them in the "customized" calendars.

Additional Context

This just adds a lot of clutter to my calendar. Both on my Laptop and my S23.
On my S23 in the Samsung Calendar, [Raid Hour] doesn't even fit on one line, making it a significant impact.

Dynamic Calendar Options for go-calendar Project

Option 2 is an awesome suggestion and was my original path. [...] So although its absolutely the right path to take, I'm not sure its perhaps the best one in this scenario.

Originally posted by @othyn in #4 (comment)

--

Hey @othyn,

I've been thinking about your comment on Option 2 in the go-calendar project, and I decided to give the dynamic option a try. I hope it's okay that I decided to split the discussion to a new issue.

If your domain is on Cloudflare, it would be super easy to set up with a Cloudflare Worker (which is free). I made a proof of concept and put it under my personal domain. It's not fully tested, so there might be some errors, but here are the links for reference:

Description URL
Main calendar (defaults to UTC) https://nit.ai/gocal.ics
Timezone-specific with timezone param https://nit.ai/gocal.ics?timezone=America/Port-au-Prince
List of valid timezones shows if you type in a wrong one https://nit.ai/gocal.ics?timezone=foo
Exclude events (blacklist style) https://nit.ai/gocal.ics?exclude=community_day
Exclude multiple events https://nit.ai/gocal.ics?exclude=community_day&exclude=elite_raids
List of valid categories shows if you type in a wrong one https://nit.ai/gocal.ics?exclude=foo
Include events (whitelist style) https://nit.ai/gocal.ics?include=pokemon_spotlight_hour
Timezone and filter combined https://nit.ai/gocal.ics?timezone=America/Port-au-Prince&exclude=season&exclude=research
Special category all_day (see notes) https://nit.ai/gocal.ics?exclude=all_day

Just a few notes:

  1. As I mentioned, this isn't fully tested, so there might be some issues.
  2. 'Exclude' and 'include' parameters can't be used together (not sure about the logic if both are used).
  3. I added a special category for 'exclude/include' called all_day, which filters all-day events across categories.

I've actually been using it with Google Calendar for about a week now with no issues.

I'd be happy to contribute the full code for this! Let me know the best way to do that, and if you need any help setting it up under your own domain.

Periodic 401 error causing calendar to desynchronize

Description

About a week or so after adding a calendar, I'll get an email from my ESP, saying the calendar has been deactivated and will no longer sync. See below.

We encountered some errors while syncing your calendar GO Calendar - Community Day.

Syncing to your GO Calendar - Community Day calendar has been disabled: [3EAFE4CA-7480-11EE-BA75-5E4721BC2B6F] An error occurred accessing your remote calendar GO Calendar - Community Day: 401 Unauthorized

I will then need to remove the calendar from my ESP, and add it again until the cycle repeats. The calendar will remain, but will never receive another update.

Version

n/a

Steps to Reproduce

  1. Create a FastMail account.
  2. Create a non-default calendar.
  3. Add any of the specific .ics files to your list of subscribed calendars.
  4. Wait ~7 days.

Screenshots

Missing Spotlight Hour, will not update after 401 error.
image

Device

n/a

Operating System

n/a

Additional Context

My ESP is Fastmail.

Some issues with Google Calendar

Description

First off, love this project! I've been looking for something exactly like this.

Having some issues when importing to Google Calendar. Here's the unexpected behavior:

  • Events don't have details like the leekduck url or image (I see in the .ics file that these details are there)
  • Events are in the Universal Time zone and I am unable to change it

I'm not sure if these issues are purely Google's fault and there's no workaround. Just wanted to report my findings

Version

N/A - pulled ics file on Jan. 4 2023

Steps to Reproduce

  1. go to google calendar settings
  2. click "Add a Calendar" > "From URL" should be this screen
  3. input the gocal url: https://github.com/othyn/go-calendar/releases/latest/download/gocal.ics

Screenshots

No response

Device

Macbook Pro, Samsung S22 Ultra

Operating System

mac, android

Additional Context

No response

Spotlight hour calendar not using correct local time

Description

Hello,

I’m currently subscribed to the .ics feed (via Google Calendar) for the spotlight hour calendar and the events are coming through at 2PM EDT instead of 6PM EDT, the expected time for my timezone. Is there a configuration I’m missing?

Version

Latest

Steps to Reproduce

Add calendar feed to Google Calendar
Events loaded
Look at calendar and see events at wrong local time (expected 6pm EDT, seen at 2pm EDT)

Screenshots

No response

Device

All

Operating System

Latest

Additional Context

No response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.