├── .gitignore
├── pom.xml
├── readme.md
└── src
├── main
└── java
│ └── com
│ └── williamramos
│ ├── Main.java
│ ├── domain
│ └── Evento.java
│ ├── enuns
│ └── TipoRecorencia.java
│ ├── facade
│ └── ConectCalendarFacade.java
│ └── service
│ ├── EventCreateService.java
│ ├── ListEventsService.java
│ └── ListTasksService.java
└── test
└── java
└── com
└── williamramos
└── MainTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Maven
2 | target/
3 | pom.xml.tag
4 | pom.xml.releaseBackup
5 | pom.xml.versionsBackup
6 | pom.xml.next
7 | release.properties
8 | dependency-reduced-pom.xml
9 | buildNumber.properties
10 | .mvn/timing.properties
11 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar
12 | .mvn/wrapper/maven-wrapper.jar
13 |
14 | # Google API Credentials
15 | src/main/resources/credentials.json
16 | tokens/
17 | *.tokens
18 | .oauth-credentials/
19 |
20 | # Eclipse m2e generated files
21 | # Eclipse Core
22 | .project
23 | # JDT-specific (Eclipse Java Development Tools)
24 | .classpath
25 | # Intellij
26 | *.iml
27 | /tokens
28 | .idea/
29 | .vscode/
30 | /src/main/resources/security.json
31 |
32 | # Compiled files
33 | *.class
34 | *.jar
35 | *.war
36 | *.ear
37 |
38 | # Logs
39 | *.log
40 | logs/
41 |
42 | # OS generated files
43 | .DS_Store
44 | .DS_Store?
45 | ._*
46 | .Spotlight-V100
47 | .Trashes
48 | ehthumbs.db
49 | Thumbs.db
50 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.williamramos
8 | Google-agenda
9 | 1.0-SNAPSHOT
10 |
11 |
12 | 17
13 | 17
14 | UTF-8
15 |
16 |
17 |
18 | com.google.api-client
19 | google-api-client
20 | 2.1.3
21 |
22 |
23 | com.google.oauth-client
24 | google-oauth-client
25 | 1.34.1
26 |
27 |
28 | com.google.apis
29 | google-api-services-calendar
30 | v3-rev20220715-2.0.0
31 |
32 |
33 | com.google.apis
34 | google-api-services-tasks
35 | v1-rev20210709-2.0.0
36 |
37 |
38 |
39 | com.google.oauth-client
40 | google-oauth-client-java6
41 | 1.11.0-beta
42 |
43 |
44 |
45 | com.google.oauth-client
46 | google-oauth-client-jetty
47 | 1.34.1
48 |
49 |
50 | org.projectlombok
51 | lombok
52 | 1.18.28
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | ## Google Calendar Integration Project
2 |
3 | ### Prerequisites
4 | - Java 17 or higher
5 | - Maven
6 | - Google account
7 |
8 | ### Project Setup Instructions
9 |
10 | 1. **Google Calendar API Setup** (One-time setup)
11 | - Go to [Google Calendar API Quickstart](https://developers.google.com/calendar/api/quickstart/java)
12 | - Click "Enable the API" button
13 | - Configure OAuth consent screen:
14 | - Choose "External" user type
15 | - Fill in your application name
16 | - Save and continue
17 | - Create credentials:
18 | - Click "Create Credentials" > "OAuth client ID"
19 | - Choose "Desktop app" as application type
20 | - Name your client ID
21 | - Download the credentials
22 | - Rename downloaded file to `credentials.json`
23 | - Place `credentials.json` in `src/main/resources/` directory
24 |
25 | 2. **Build and Run**
26 | ```bash
27 | # Clone or extract the project
28 | cd [project-directory]
29 |
30 | # Build the project
31 | mvn clean install
32 |
33 | # Run the application
34 | mvn exec:java -Dexec.mainClass="com.williamramos.Main"
35 | ```
36 |
37 | 3. **First Run**
38 | - On first execution, the application will open your browser
39 | - Log in with your Google account
40 | - Grant the requested calendar permissions
41 | - The application will create a `tokens` directory to store your authentication
42 |
43 | ### Features
44 | - Create calendar events
45 | - List tasks
46 | - List calendar events
47 |
48 | ### Security Note
49 | - Never share your `credentials.json` or generated tokens
50 | - Each client should generate their own credentials
51 | - The `tokens` directory contains sensitive authentication data
52 |
53 | ### Troubleshooting
54 | 1. **Missing credentials.json**
55 | - Ensure you've followed the Google Calendar API setup steps
56 | - Check if credentials.json is in the correct directory
57 |
58 | 2. **Authentication Errors**
59 | - Delete the `tokens` directory and try again
60 | - Ensure you're using a Google account with calendar access
61 |
62 | 3. **Build Errors**
63 | - Verify Java 17 is installed: `java -version`
64 | - Verify Maven is installed: `mvn -version`
65 |
66 | ### Support
67 | For any issues or questions, please contact:
68 | [Your Contact Information]
69 |
70 |
71 |
--------------------------------------------------------------------------------
/src/main/java/com/williamramos/Main.java:
--------------------------------------------------------------------------------
1 | package com.williamramos;
2 |
3 | import java.io.IOException;
4 | import java.time.LocalDateTime;
5 | import java.util.List;
6 |
7 | import com.google.api.services.calendar.model.Event;
8 | import com.google.api.services.tasks.model.Task;
9 | import com.williamramos.service.EventCreateService;
10 | import com.williamramos.service.ListEventsService;
11 | import com.williamramos.service.ListTasksService;
12 |
13 | /**
14 | * Hello world!
15 | */
16 | public class Main {
17 | public static void main(String[] args) throws IOException {
18 | save();
19 | listarTarefas();
20 | listarEventos();
21 |
22 | }
23 | public static Event save() throws IOException {
24 | var service = new EventCreateService();
25 | service.createEvent("Evento Sucesso Programado", "Festa do Amanhecer");
26 | service.start(LocalDateTime.now().plusDays(3).toString());
27 | service.end(LocalDateTime.now().plusDays(7).toString());
28 | service.addParticipantes("wulliamcostaramos@gmail.com");
29 | service.addParticipantes("denizequeiroz2001@gmail.com");
30 | return service.save();
31 | }
32 |
33 | public static void listarTarefas(){
34 | var tarefaServices = new ListTasksService();
35 | System.out.println("Listando tarefas");
36 | List tarefas = tarefaServices.list();
37 | if(!tarefas.isEmpty()){
38 | for (Task tarefa : tarefas) {
39 | System.out.printf("Tarefa: %s - %s \n",tarefa.getTitle(), tarefa.getDue()); }
40 | }
41 | }
42 | public static void listarEventos(){
43 | var service = new ListEventsService();
44 |
45 | List items = service.list();
46 |
47 |
48 | items.forEach(item -> System.out.printf("id: %s \nNome: %s \nDescrição : %s \n######################################################## \n", item.getId(),item.getSummary(), item.getDescription()));
49 |
50 | items.forEach(item -> {
51 | if (item.getRecurrence() != null) {
52 | System.out.println("Listando eventos recorrentes");
53 | for (String en : item.getRecurrence()) {
54 | System.out.printf("%s \n", en);
55 | }
56 | }
57 | });
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/williamramos/domain/Evento.java:
--------------------------------------------------------------------------------
1 | package com.williamramos.domain;
2 |
3 | import com.williamramos.enuns.TipoRecorencia;
4 | import lombok.Data;
5 |
6 | import java.time.LocalDateTime;
7 | import java.util.List;
8 | @Data
9 | public class Evento {
10 | private String nome;
11 | private String descricao;
12 | private List participantes;
13 | private String recorrencia;
14 | private TipoRecorencia tipoRecorencia;
15 | private LocalDateTime inicio;
16 | private LocalDateTime fim;
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/williamramos/enuns/TipoRecorencia.java:
--------------------------------------------------------------------------------
1 | package com.williamramos.enuns;
2 |
3 | public enum TipoRecorencia {
4 | DIARIO,
5 | SEMANAL,
6 | MENSAL,
7 | ANUAL
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/williamramos/facade/ConectCalendarFacade.java:
--------------------------------------------------------------------------------
1 | package com.williamramos.facade;
2 |
3 | import com.google.api.client.auth.oauth2.Credential;
4 | import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
5 | import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
6 | import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
7 | import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
8 | import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
9 | import com.google.api.client.http.HttpTransport;
10 | import com.google.api.client.http.javanet.NetHttpTransport;
11 | import com.google.api.client.json.JsonFactory;
12 | import com.google.api.client.json.gson.GsonFactory;
13 | import com.google.api.client.util.store.FileDataStoreFactory;
14 | import com.google.api.services.calendar.Calendar;
15 | import com.google.api.services.calendar.CalendarScopes;
16 | import com.google.api.services.tasks.Tasks;
17 | import com.google.api.services.tasks.TasksScopes;
18 |
19 | import java.io.IOException;
20 | import java.io.InputStream;
21 | import java.io.InputStreamReader;
22 | import java.security.GeneralSecurityException;
23 | import java.util.Arrays;
24 | import java.util.List;
25 |
26 | import static com.google.api.services.calendar.CalendarScopes.CALENDAR_EVENTS;
27 |
28 | public class ConectCalendarFacade {
29 | private static final String APPLICATION_NAME = "Agenda";
30 |
31 | private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
32 |
33 | private static final String TOKENS_DIRECTORY_PATH = "tokens";
34 | private static final List SCOPES = Arrays.asList(CalendarScopes.CALENDAR, CALENDAR_EVENTS, TasksScopes.TASKS);
35 |
36 | private static final String CREDENTIALS_FILE_PATH = "/security.json";
37 | public static final String AQUIVO_DE_CREDENCIAIS_NAO_ENCONTRADO = "Aquivo de credenciais nao Encontrado";
38 | public static final String FALHA_AO_TENTAR_SE_CONECTAR_AO_GOOGLE = "Falha ao tentar se conectar ao Google";
39 | public static final String ERRO_DESCONHECIDO = "Erro Desconhecido";
40 |
41 |
42 |
43 | private static Credential getCredentials(final NetHttpTransport httpTransport) {
44 | try {
45 | InputStream inputStream = ConectCalendarFacade.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
46 | assert inputStream != null;
47 | GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(inputStream));
48 | GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, JSON_FACTORY, clientSecrets, SCOPES).setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH))).setAccessType("offline").build();
49 | LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
50 | return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
51 | } catch (IOException e) {
52 | throw new RuntimeException(AQUIVO_DE_CREDENCIAIS_NAO_ENCONTRADO);
53 | } catch (GeneralSecurityException e) {
54 | throw new RuntimeException(FALHA_AO_TENTAR_SE_CONECTAR_AO_GOOGLE);
55 | } catch (Exception e) {
56 | throw new RuntimeException(ERRO_DESCONHECIDO);
57 | }
58 | }
59 |
60 |
61 | public static Calendar getCalendarService() {
62 | try {
63 | final NetHttpTransport http = GoogleNetHttpTransport.newTrustedTransport();
64 | return new Calendar.Builder(http, JSON_FACTORY, getCredentials(http)).setApplicationName(APPLICATION_NAME).build();
65 | } catch (GeneralSecurityException e) {
66 | throw new RuntimeException(e);
67 | } catch (IOException e) {
68 | throw new RuntimeException(e);
69 | }
70 | }
71 |
72 | public static Tasks getTasksService(){
73 | try {
74 | InputStream inputStream = ConectCalendarFacade.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
75 | HttpTransport httpTransport = com.google.api.client.googleapis.javanet.GoogleNetHttpTransport.newTrustedTransport();
76 | return new Tasks.Builder(httpTransport, JSON_FACTORY, getCredentials((NetHttpTransport) httpTransport)).setApplicationName(APPLICATION_NAME).build();
77 | } catch (GeneralSecurityException e) {
78 | throw new RuntimeException(e);
79 | } catch (IOException e) {
80 | throw new RuntimeException(e);
81 | }
82 | }
83 |
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/com/williamramos/service/EventCreateService.java:
--------------------------------------------------------------------------------
1 | package com.williamramos.service;
2 |
3 | import com.google.api.client.util.DateTime;
4 | import com.google.api.services.calendar.Calendar;
5 | import com.google.api.services.calendar.model.Event;
6 | import com.google.api.services.calendar.model.EventAttendee;
7 | import com.google.api.services.calendar.model.EventDateTime;
8 | import com.williamramos.facade.ConectCalendarFacade;
9 |
10 | import java.io.IOException;
11 | import java.time.LocalDateTime;
12 | import java.util.ArrayList;
13 | import java.util.Arrays;
14 | import java.util.List;
15 | import java.util.TimeZone;
16 |
17 | public class EventCreateService {
18 | private Event event;
19 | private DateTime dateTimeStart;
20 | private DateTime dateTimeEnd;
21 | private List participantes;
22 | private Calendar service;
23 | private static final String calendarId = "primary";
24 |
25 | public EventCreateService() {
26 | this.service = ConectCalendarFacade.getCalendarService();
27 | this.participantes = new ArrayList<>();
28 | }
29 |
30 | public Event createEvent(String title, String description) {
31 | this.event = new Event();
32 | this.event.setSummary(title);
33 | this.event.setDescription(description);
34 | return event;
35 | }
36 |
37 | public Event start(String data) {
38 | DateTime startDateTime = new DateTime(data); // Data e hora inicial
39 | EventDateTime start = new EventDateTime()
40 | .setDateTime(startDateTime)
41 | .setTimeZone(TimeZone.getTimeZone("America/Araguaina").getID());
42 | this.event.setStart(start);
43 | return this.event;
44 | }
45 |
46 | public Event end(String data) {
47 |
48 | DateTime endDateTime = new DateTime(data); // Data e hora final
49 | EventDateTime end = new EventDateTime()
50 | .setDateTime(endDateTime)
51 | .setTimeZone(TimeZone.getTimeZone("America/Araguaina").getID());
52 | this.event.setEnd(end);
53 | return this.event;
54 | }
55 |
56 | public void addParticipantes(String... particpantes) {
57 | Arrays.stream(particpantes).forEach(participante -> {
58 | var atendente = new EventAttendee();
59 | atendente.setEmail(participante);
60 | this.participantes.add(atendente);
61 | });
62 |
63 | }
64 |
65 | public Event save() {
66 | try {
67 | return service.events().insert(calendarId, this.event).execute();
68 | } catch (IOException e) {
69 | throw new RuntimeException(e);
70 | }
71 |
72 | }
73 |
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/williamramos/service/ListEventsService.java:
--------------------------------------------------------------------------------
1 | package com.williamramos.service;
2 |
3 | import java.io.IOException;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import com.google.api.client.util.DateTime;
8 | import com.google.api.services.calendar.Calendar;
9 | import com.google.api.services.calendar.model.Event;
10 | import com.google.api.services.calendar.model.Events;
11 | import com.williamramos.facade.ConectCalendarFacade;
12 |
13 | public class ListEventsService {
14 | private List eventos;
15 | private Calendar calendar;
16 |
17 | public ListEventsService() {
18 | this.calendar = ConectCalendarFacade.getCalendarService();
19 | this.eventos = new ArrayList<>();
20 | }
21 |
22 | public List list() {
23 | try {
24 | DateTime dataDeInicio = new DateTime(System.currentTimeMillis() - 360 * 24 * 60 * 60 * 1000);
25 | Events events = this.calendar.events().list("primary")
26 | .setMaxResults(100)
27 | .setSingleEvents(false)
28 | .setTimeMin(dataDeInicio)
29 | .execute();
30 | this.eventos = events.getItems();
31 | return this.eventos;
32 | } catch (IOException e) {
33 | throw new RuntimeException(e.getMessage());
34 | }
35 |
36 | }
37 |
38 | public List list(String calendarId, Integer maxResult, boolean singleEvents) {
39 | try {
40 | Events events = this.calendar.events().list(calendarId)
41 | .setMaxResults(maxResult)
42 | .setSingleEvents(singleEvents)
43 | .execute();
44 | this.eventos = events.getItems();
45 | return this.eventos;
46 | } catch (IOException e) {
47 | throw new RuntimeException(e.getMessage());
48 | }
49 |
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/williamramos/service/ListTasksService.java:
--------------------------------------------------------------------------------
1 | package com.williamramos.service;
2 |
3 | import com.google.api.services.tasks.Tasks;
4 | import com.google.api.services.tasks.model.Task;
5 | import com.williamramos.facade.ConectCalendarFacade;
6 |
7 | import java.io.IOException;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | public class ListTasksService {
12 | private List tasks;
13 | private Tasks service;
14 |
15 | public ListTasksService() {
16 | this.service = ConectCalendarFacade.getTasksService();
17 | this.tasks = new ArrayList<>();
18 | }
19 |
20 | public List list() {
21 | try {
22 | String taskListId = "@default";
23 | Tasks.TasksOperations.List request = service.tasks().list(taskListId);
24 | var tarefas = request.execute();
25 | return tarefas.getItems();
26 | } catch (IOException e) {
27 | throw new RuntimeException(e.getMessage());
28 | }
29 |
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/test/java/com/williamramos/MainTest.java:
--------------------------------------------------------------------------------
1 | package com.williamramos;
2 |
3 | /**
4 | * A simple unit test
5 | */
6 | public class MainTest
7 | {
8 | /**
9 | * Rigorous Test :-)
10 | */
11 |
12 | public void shouldAnswerWithTrue()
13 | {
14 |
15 | }
16 | }
17 |
--------------------------------------------------------------------------------