├── .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 | --------------------------------------------------------------------------------