7.diff (36694B)
1 diff --git a/Gopkg.lock b/Gopkg.lock 2 index 7859130..629ec69 100644 3 --- a/Gopkg.lock 4 +++ b/Gopkg.lock 5 @@ -13,6 +13,12 @@ 6 packages = ["."] 7 revision = "a7fc80c8060c2544fe5d4dae465b584f8e9b4e27" 8 9 +[[projects]] 10 + name = "github.com/mattn/go-sqlite3" 11 + packages = ["."] 12 + revision = "6c771bb9887719704b210e87e934f08be014bdb1" 13 + version = "v1.6.0" 14 + 15 [[projects]] 16 branch = "master" 17 name = "github.com/shibukawa/configdir" 18 @@ -34,6 +40,6 @@ 19 [solve-meta] 20 analyzer-name = "dep" 21 analyzer-version = 1 22 - inputs-digest = "c22db96d1e74b32e9427a6f762b2be5797dcc8426407dc4769795fe6ca7296be" 23 + inputs-digest = "f746b36e895639f6b0cbe2cb4d928637d254f83f60346a95eaf5c0f383683229" 24 solver-name = "gps-cdcl" 25 solver-version = 1 26 diff --git a/cmd/root.go b/cmd/root.go 27 index 148f65a..9b10937 100644 28 --- a/cmd/root.go 29 +++ b/cmd/root.go 30 @@ -19,7 +19,8 @@ import ( 31 "os" 32 33 "github.com/Nordgedanken/Morpheusv2/pkg/app" 34 - dbImpl "github.com/Nordgedanken/Morpheusv2/pkg/db/implementation" 35 + "github.com/Nordgedanken/Morpheusv2/pkg/db/sqlite" 36 + "github.com/Nordgedanken/Morpheusv2/pkg/util" 37 "github.com/shibukawa/configdir" 38 "github.com/spf13/cobra" 39 "io" 40 @@ -47,7 +48,7 @@ var rootCmd = &cobra.Command{ 41 } 42 43 // os.OpenFile opens the file where the log is supposed to be written to 44 - logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) 45 + logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0600) 46 if err != nil { 47 return err 48 } 49 @@ -59,7 +60,8 @@ var rootCmd = &cobra.Command{ 50 log.SetOutput(mw) 51 52 // dbImpl.Init() generates the needed tables if needed before the app starts 53 - err = dbImpl.Init() 54 + util.DB = &sqlite.SQLite{} 55 + err = util.DB.Init() 56 if err != nil { 57 return err 58 } 59 diff --git a/pkg/app/main.go b/pkg/app/main.go 60 index 3832900..255f074 100644 61 --- a/pkg/app/main.go 62 +++ b/pkg/app/main.go 63 @@ -15,7 +15,10 @@ 64 package app 65 66 import ( 67 + "database/sql" 68 + "github.com/Nordgedanken/Morpheusv2/pkg/loginUI" 69 "github.com/Nordgedanken/Morpheusv2/pkg/mainUI" 70 + "github.com/Nordgedanken/Morpheusv2/pkg/util" 71 "github.com/matrix-org/gomatrix" 72 "github.com/therecipe/qt/core" 73 "github.com/therecipe/qt/gui" 74 @@ -36,11 +39,20 @@ func Start(argsArg []string) error { 75 76 initApp() 77 78 - mainUIS := mainUI.NewMainUI(windowWidth, windowHeight, window) 79 - SetNewWindow(mainUIS, window) 80 + _, err := util.DB.GetCurrentUser() 81 + // We special case ErrNoRows because this is expected to happen if user is missing 82 + if err == sql.ErrNoRows { 83 + loginUIs := loginUI.NewLoginUI(windowWidth, windowHeight, window) 84 + SetNewWindow(loginUIs, window) 85 + } else if err != nil { 86 + return err 87 + } else { 88 + mainUIs := mainUI.NewMainUI(windowWidth, windowHeight, window) 89 + SetNewWindow(mainUIs, window) 90 + } 91 92 widgets.QApplication_Exec() 93 - 94 + 95 return nil 96 } 97 98 @@ -65,7 +77,7 @@ func initApp() { 99 window.Resize2(windowWidth, windowHeight) 100 window.Move2(windowX, windowY) 101 102 - app.ConnectQuit(func() { 103 + window.ConnectCloseEvent(func(event *gui.QCloseEvent) { 104 log.Println("Morpheus closed") 105 }) 106 107 diff --git a/pkg/app/ui.go b/pkg/app/ui.go 108 index 37ced17..7273079 100644 109 --- a/pkg/app/ui.go 110 +++ b/pkg/app/ui.go 111 @@ -1,3 +1,17 @@ 112 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 113 +// 114 +// Licensed under the Apache License, Version 2.0 (the "License"); 115 +// you may not use this file except in compliance with the License. 116 +// You may obtain a copy of the License at 117 +// 118 +// http://www.apache.org/licenses/LICENSE-2.0 119 +// 120 +// Unless required by applicable law or agreed to in writing, software 121 +// distributed under the License is distributed on an "AS IS" BASIS, 122 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123 +// See the License for the specific language governing permissions and 124 +// limitations under the License. 125 + 126 package app 127 128 import ( 129 diff --git a/pkg/db/db.go b/pkg/db/db.go 130 index 0ffaede..27f04b8 100644 131 --- a/pkg/db/db.go 132 +++ b/pkg/db/db.go 133 @@ -1,14 +1,37 @@ 134 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 135 +// 136 +// Licensed under the Apache License, Version 2.0 (the "License"); 137 +// you may not use this file except in compliance with the License. 138 +// You may obtain a copy of the License at 139 +// 140 +// http://www.apache.org/licenses/LICENSE-2.0 141 +// 142 +// Unless required by applicable law or agreed to in writing, software 143 +// distributed under the License is distributed on an "AS IS" BASIS, 144 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145 +// See the License for the specific language governing permissions and 146 +// limitations under the License. 147 + 148 package db 149 150 -import "github.com/Nordgedanken/Morpheusv2/pkg/matrix" 151 +import ( 152 + "database/sql" 153 + "github.com/Nordgedanken/Morpheusv2/pkg/matrix" 154 +) 155 156 // DB defines a Interface to allow multiple DB Implementations 157 type DB interface { 158 + Init() error 159 + Open() *sql.DB 160 + 161 SaveRoom(Room matrix.Room) error 162 - GetRooms() (rooms map[string]matrix.Room, err error) 163 - GetRoom(roomID string) (room matrix.Room, err error) 164 + GetRooms() (roomsR []matrix.Room, err error) 165 + GetRoom(roomID string) (roomR matrix.Room, err error) 166 167 SaveUser(user matrix.User) error 168 - GetUsers() (map[string]matrix.User, error) 169 - GetCurrentUser() (matrix.User, error) 170 + GetUser(userID string) (userR matrix.User, err error) 171 + GetCurrentUser() (userR matrix.User, err error) 172 + 173 + SaveMessage(message matrix.Message) error 174 + GetMessage(eventID string) (messageR matrix.Message, err error) 175 } 176 diff --git a/pkg/db/sqlite/db.go b/pkg/db/sqlite/db.go 177 new file mode 100644 178 index 0000000..fa80421 179 --- /dev/null 180 +++ b/pkg/db/sqlite/db.go 181 @@ -0,0 +1,62 @@ 182 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 183 +// 184 +// Licensed under the Apache License, Version 2.0 (the "License"); 185 +// you may not use this file except in compliance with the License. 186 +// You may obtain a copy of the License at 187 +// 188 +// http://www.apache.org/licenses/LICENSE-2.0 189 +// 190 +// Unless required by applicable law or agreed to in writing, software 191 +// distributed under the License is distributed on an "AS IS" BASIS, 192 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 193 +// See the License for the specific language governing permissions and 194 +// limitations under the License. 195 + 196 +package sqlite 197 + 198 +import ( 199 + "database/sql" 200 + "fmt" 201 + _ "github.com/mattn/go-sqlite3" // Go-sqlite3 side effect import needed to use SQLite3 databases 202 + "github.com/shibukawa/configdir" 203 + "log" 204 + "path/filepath" 205 +) 206 + 207 +// Init prepares the DB by opening it and creating the required tables if needed 208 +func (s *SQLite) Init() (err error) { 209 + log.Println("Start setting up DB") 210 + var openErr error 211 + 212 + // Open the data.db file. It will be created if it doesn't exist. 213 + configDirs := configdir.New("Nordgedanken", "Morpheusv2") 214 + filePath := filepath.ToSlash(configDirs.QueryFolders(configdir.Global)[0].Path) 215 + 216 + log.Println("DBFilePath: ", filePath+"/data.db") 217 + s.db, openErr = sql.Open("sqlite3", filePath+"/data.db") 218 + if openErr != nil { 219 + err = openErr 220 + return 221 + } 222 + 223 + log.Println("Creating DB Tables if needed") 224 + createTables := `CREATE TABLE IF NOT EXISTS users (id varchar not null primary key, display_name text, avatar text, access_token text, own integer); 225 + CREATE TABLE IF NOT EXISTS messages (id varchar not null primary key, author_id varchar, message text, timestamp datetime, pure_event text); 226 + CREATE TABLE IF NOT EXISTS rooms (id varchar not null primary key, room_aliases text, room_name text, room_avatar text, room_topic text, room_messages text); 227 + ` 228 + _, execErr := s.db.Exec(createTables) 229 + if execErr != nil { 230 + err = fmt.Errorf("DB EXEC ERR: %s", execErr) 231 + return 232 + } 233 + log.Println("Finished setting DB Setup") 234 + return 235 +} 236 + 237 +// Open returns the in Init() created db variable 238 +func (s *SQLite) Open() *sql.DB { 239 + if s.db != nil { 240 + return s.db 241 + } 242 + return nil 243 +} 244 diff --git a/pkg/db/sqlite/messages.go b/pkg/db/sqlite/messages.go 245 new file mode 100644 246 index 0000000..6b709d7 247 --- /dev/null 248 +++ b/pkg/db/sqlite/messages.go 249 @@ -0,0 +1,93 @@ 250 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 251 +// 252 +// Licensed under the Apache License, Version 2.0 (the "License"); 253 +// you may not use this file except in compliance with the License. 254 +// You may obtain a copy of the License at 255 +// 256 +// http://www.apache.org/licenses/LICENSE-2.0 257 +// 258 +// Unless required by applicable law or agreed to in writing, software 259 +// distributed under the License is distributed on an "AS IS" BASIS, 260 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 261 +// See the License for the specific language governing permissions and 262 +// limitations under the License. 263 + 264 +package sqlite 265 + 266 +import ( 267 + "encoding/json" 268 + "github.com/Nordgedanken/Morpheusv2/pkg/matrix" 269 + "github.com/Nordgedanken/Morpheusv2/pkg/matrix/messages" 270 + "github.com/matrix-org/gomatrix" 271 + "time" 272 +) 273 + 274 +// SaveMessage saves message Events to the DB 275 +func (s *SQLite) SaveMessage(message matrix.Message) error { 276 + if s.db == nil { 277 + s.db = s.Open() 278 + } 279 + 280 + tx, err := s.db.Begin() 281 + if err != nil { 282 + return err 283 + } 284 + 285 + stmt, err := tx.Prepare("INSERT INTO messages (id, author_id, message, timestamp, pure_event) VALUES (?, ?, ?, ?, ?)") 286 + if err != nil { 287 + return err 288 + } 289 + defer stmt.Close() 290 + 291 + id := message.GetEventID() 292 + authorID := message.GetAuthorMXID() 293 + messageS := message.GetMessage() 294 + timestampR := message.GetTimestamp() 295 + timestamp := timestampR.Format("2006-01-02 15:04:05") 296 + pureEvent := message.GetEvent() 297 + _, err = stmt.Exec(id, authorID, messageS, timestamp, pureEvent) 298 + if err != nil { 299 + return err 300 + } 301 + 302 + return tx.Commit() 303 +} 304 + 305 +// GetMessage returns the Message where the id matches the eventID 306 +func (s *SQLite) GetMessage(eventID string) (messageR matrix.Message, err error) { 307 + if s.db == nil { 308 + s.db = s.Open() 309 + } 310 + 311 + stmt, err := s.db.Prepare(`SELECT author_id, message, timestamp, pure_event FROM messages WHERE id=$1`) 312 + if err != nil { 313 + return 314 + } 315 + defer stmt.Close() 316 + 317 + row := stmt.QueryRow(eventID) 318 + 319 + var authorID string 320 + var messageS string 321 + var timestamp time.Time 322 + var pureEvent string 323 + err = row.Scan(&authorID, &messageS, ×tamp, &pureEvent) 324 + if err != nil { 325 + return 326 + } 327 + 328 + messageI := &messages.Message{} 329 + messageI.SetEventID(eventID) 330 + messageI.SetAuthorMXID(authorID) 331 + messageI.SetMessage(messageS) 332 + messageI.SetTimestamp(×tamp) 333 + var gomatrixEvent gomatrix.Event 334 + err = json.Unmarshal([]byte(pureEvent), &gomatrixEvent) 335 + if err != nil { 336 + return 337 + } 338 + messageI.SetEvent(&gomatrixEvent) 339 + 340 + messageR = messageI 341 + return 342 +} 343 diff --git a/pkg/db/sqlite/rooms.go b/pkg/db/sqlite/rooms.go 344 new file mode 100644 345 index 0000000..1bfd627 346 --- /dev/null 347 +++ b/pkg/db/sqlite/rooms.go 348 @@ -0,0 +1,172 @@ 349 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 350 +// 351 +// Licensed under the Apache License, Version 2.0 (the "License"); 352 +// you may not use this file except in compliance with the License. 353 +// You may obtain a copy of the License at 354 +// 355 +// http://www.apache.org/licenses/LICENSE-2.0 356 +// 357 +// Unless required by applicable law or agreed to in writing, software 358 +// distributed under the License is distributed on an "AS IS" BASIS, 359 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 360 +// See the License for the specific language governing permissions and 361 +// limitations under the License. 362 + 363 +package sqlite 364 + 365 +import ( 366 + "encoding/json" 367 + "github.com/Nordgedanken/Morpheusv2/pkg/matrix" 368 + "github.com/Nordgedanken/Morpheusv2/pkg/matrix/rooms" 369 +) 370 + 371 +// SaveRoom saves a Room into the sqlite DB 372 +func (s *SQLite) SaveRoom(Room matrix.Room) error { 373 + if s.db == nil { 374 + s.db = s.Open() 375 + } 376 + 377 + tx, err := s.db.Begin() 378 + if err != nil { 379 + return err 380 + } 381 + 382 + stmt, err := tx.Prepare("INSERT INTO rooms (room_aliases, id, room_name, room_avatar, room_topic, room_messages) VALUES (?, ?, ?, ?, ?, ?)") 383 + if err != nil { 384 + return err 385 + } 386 + defer stmt.Close() 387 + 388 + aliases := Room.GetRoomAliases() 389 + aliasesBytes, err := json.Marshal(aliases) 390 + if err != nil { 391 + return err 392 + } 393 + aliasesS := string(aliasesBytes) 394 + roomID := Room.GetRoomID() 395 + name, err := Room.GetName() 396 + if err != nil { 397 + return err 398 + } 399 + avatar, err := Room.GetAvatar() 400 + if err != nil { 401 + return err 402 + } 403 + topic, err := Room.GetTopic() 404 + if err != nil { 405 + return err 406 + } 407 + 408 + messages := Room.GetMessages() 409 + if err != nil { 410 + return err 411 + } 412 + var messageIDs []string 413 + for _, v := range messages { 414 + messageIDs = append(messageIDs, v.GetEventID()) 415 + } 416 + 417 + _, err = stmt.Exec(aliasesS, roomID, name, string(avatar), topic, messageIDs) 418 + if err != nil { 419 + return err 420 + } 421 + return tx.Commit() 422 +} 423 + 424 +// GetRooms returns all Rooms from the Database 425 +func (s *SQLite) GetRooms() (roomsR []matrix.Room, err error) { 426 + if s.db == nil { 427 + s.db = s.Open() 428 + } 429 + 430 + rows, err := s.db.Query("SELECT id, room_aliases, room_name, room_avatar, room_topic, room_messages FROM rooms") 431 + if err != nil { 432 + return 433 + } 434 + defer rows.Close() 435 + 436 + for rows.Next() { 437 + var roomID string 438 + var roomAliases string 439 + var roomName string 440 + var roomAvatar string 441 + var roomTopic string 442 + var roomMessages string 443 + err = rows.Scan(&roomID, &roomAliases, &roomName, &roomAvatar, &roomTopic, &roomMessages) 444 + if err != nil { 445 + return 446 + } 447 + 448 + roomI := &rooms.Room{} 449 + roomI.SetRoomID(roomID) 450 + var aliases []string 451 + err = json.Unmarshal([]byte(roomAliases), &aliases) 452 + if err != nil { 453 + return 454 + } 455 + roomI.SetRoomAliases(aliases) 456 + roomI.SetName(roomName) 457 + roomI.SetAvatar([]byte(roomAvatar)) 458 + roomI.SetTopic(roomTopic) 459 + var messageIDs []string 460 + err = json.Unmarshal([]byte(roomMessages), &messageIDs) 461 + if err != nil { 462 + return 463 + } 464 + // TODO Convert IDs to messages slice using another call or from the beginning on using a JOIN 465 + //roomI.SetMessages(messages) 466 + 467 + roomsR = append(roomsR, roomI) 468 + } 469 + 470 + // get any error encountered during iteration 471 + err = rows.Err() 472 + return 473 +} 474 + 475 +// GetRoom returns the Room where the id matches the roomID 476 +func (s *SQLite) GetRoom(roomID string) (roomR matrix.Room, err error) { 477 + if s.db == nil { 478 + s.db = s.Open() 479 + } 480 + 481 + stmt, err := s.db.Prepare(`SELECT room_aliases, room_name, room_avatar, room_topic, room_messages FROM rooms WHERE id=$1`) 482 + if err != nil { 483 + return 484 + } 485 + defer stmt.Close() 486 + 487 + row := stmt.QueryRow(roomID) 488 + 489 + var roomAliases string 490 + var roomName string 491 + var roomAvatar string 492 + var roomTopic string 493 + var roomMessages string 494 + err = row.Scan(&roomAliases, &roomName, &roomAvatar, &roomTopic, &roomMessages) 495 + if err != nil { 496 + return 497 + } 498 + 499 + roomI := &rooms.Room{} 500 + roomI.SetRoomID(roomID) 501 + var aliases []string 502 + err = json.Unmarshal([]byte(roomAliases), &aliases) 503 + if err != nil { 504 + return 505 + } 506 + roomI.SetRoomAliases(aliases) 507 + roomI.SetName(roomName) 508 + roomI.SetAvatar([]byte(roomAvatar)) 509 + roomI.SetTopic(roomTopic) 510 + var messageIDs []string 511 + err = json.Unmarshal([]byte(roomMessages), &messageIDs) 512 + if err != nil { 513 + return 514 + } 515 + // TODO Convert IDs to messages slice using another call or from the beginning on using a JOIN 516 + //roomI.SetMessages(messages) 517 + 518 + roomR = roomI 519 + return 520 +} 521 diff --git a/pkg/db/sqlite/struct.go b/pkg/db/sqlite/struct.go 522 new file mode 100644 523 index 0000000..6497773 524 --- /dev/null 525 +++ b/pkg/db/sqlite/struct.go 526 @@ -0,0 +1,22 @@ 527 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 528 +// 529 +// Licensed under the Apache License, Version 2.0 (the "License"); 530 +// you may not use this file except in compliance with the License. 531 +// You may obtain a copy of the License at 532 +// 533 +// http://www.apache.org/licenses/LICENSE-2.0 534 +// 535 +// Unless required by applicable law or agreed to in writing, software 536 +// distributed under the License is distributed on an "AS IS" BASIS, 537 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 538 +// See the License for the specific language governing permissions and 539 +// limitations under the License. 540 + 541 +package sqlite 542 + 543 +import "database/sql" 544 + 545 +// SQLite implements a SQLite database for the db.DB interface 546 +type SQLite struct { 547 + db *sql.DB 548 +} 549 diff --git a/pkg/db/sqlite/users.go b/pkg/db/sqlite/users.go 550 new file mode 100644 551 index 0000000..e78a6a6 552 --- /dev/null 553 +++ b/pkg/db/sqlite/users.go 554 @@ -0,0 +1,125 @@ 555 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 556 +// 557 +// Licensed under the Apache License, Version 2.0 (the "License"); 558 +// you may not use this file except in compliance with the License. 559 +// You may obtain a copy of the License at 560 +// 561 +// http://www.apache.org/licenses/LICENSE-2.0 562 +// 563 +// Unless required by applicable law or agreed to in writing, software 564 +// distributed under the License is distributed on an "AS IS" BASIS, 565 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 566 +// See the License for the specific language governing permissions and 567 +// limitations under the License. 568 + 569 +package sqlite 570 + 571 +import ( 572 + "github.com/Nordgedanken/Morpheusv2/pkg/matrix" 573 + "github.com/Nordgedanken/Morpheusv2/pkg/matrix/users" 574 + "github.com/matrix-org/gomatrix" 575 + "strings" 576 +) 577 + 578 +// SaveUser saves a matrix User to the User table 579 +func (s *SQLite) SaveUser(user matrix.User) error { 580 + if s.db == nil { 581 + s.db = s.Open() 582 + } 583 + 584 + tx, err := s.db.Begin() 585 + if err != nil { 586 + return err 587 + } 588 + 589 + stmt, err := tx.Prepare("INSERT INTO users (id, display_name, avatar) VALUES (?, ?, ?)") 590 + if err != nil { 591 + return err 592 + } 593 + defer stmt.Close() 594 + displayName, err := user.GetDisplayName("") 595 + if err != nil { 596 + return err 597 + } 598 + avatar, err := user.GetAvatar("") 599 + if err != nil { 600 + return err 601 + } 602 + mxid := user.GetMXID() 603 + _, err = stmt.Exec(mxid, displayName, string(avatar)) 604 + if err != nil { 605 + return err 606 + } 607 + 608 + return tx.Commit() 609 +} 610 + 611 +// GetCurrentUser returns the current user including a ready gomatrix client 612 +func (s *SQLite) GetCurrentUser() (userR matrix.User, err error) { 613 + if s.db == nil { 614 + s.db = s.Open() 615 + } 616 + 617 + stmt, err := s.db.Prepare(`SELECT id, display_name, avatar, access_token FROM users WHERE own=1`) 618 + if err != nil { 619 + return 620 + } 621 + defer stmt.Close() 622 + 623 + row := stmt.QueryRow() 624 + 625 + var mxid string 626 + var displayName string 627 + var avatar string 628 + var accessToken string 629 + err = row.Scan(&mxid, &displayName, &avatar, &accessToken) 630 + if err != nil { 631 + return 632 + } 633 + 634 + userI := &users.User{} 635 + userI.SetMXID(mxid) 636 + userI.SetDisplayName("", displayName) 637 + userI.SetAvatar("", []byte(avatar)) 638 + 639 + splitUser := strings.Split(mxid, ":") 640 + domain := strings.TrimPrefix(mxid, splitUser[0]+":") 641 + client, err := gomatrix.NewClient(domain, mxid, accessToken) 642 + if err != nil { 643 + return 644 + } 645 + userI.SetCli(client) 646 + 647 + userR = userI 648 + return 649 +} 650 + 651 +// GetUser returns a user matching the mxid of the argument 652 +func (s *SQLite) GetUser(userID string) (userR matrix.User, err error) { 653 + if s.db == nil { 654 + s.db = s.Open() 655 + } 656 + 657 + stmt, err := s.db.Prepare(`SELECT display_name, avatar FROM users WHERE id=$1`) 658 + if err != nil { 659 + return 660 + } 661 + defer stmt.Close() 662 + 663 + row := stmt.QueryRow(userID) 664 + 665 + var displayName string 666 + var avatar string 667 + err = row.Scan(&displayName, &avatar) 668 + if err != nil { 669 + return 670 + } 671 + 672 + userI := &users.User{} 673 + userI.SetMXID(userID) 674 + userI.SetDisplayName("", displayName) 675 + userI.SetAvatar("", []byte(avatar)) 676 + 677 + userR = userI 678 + return 679 +} 680 diff --git a/pkg/loginUI/loginUI.go b/pkg/loginUI/loginUI.go 681 new file mode 100644 682 index 0000000..fa3d993 683 --- /dev/null 684 +++ b/pkg/loginUI/loginUI.go 685 @@ -0,0 +1,77 @@ 686 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 687 +// 688 +// Licensed under the Apache License, Version 2.0 (the "License"); 689 +// you may not use this file except in compliance with the License. 690 +// You may obtain a copy of the License at 691 +// 692 +// http://www.apache.org/licenses/LICENSE-2.0 693 +// 694 +// Unless required by applicable law or agreed to in writing, software 695 +// distributed under the License is distributed on an "AS IS" BASIS, 696 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 697 +// See the License for the specific language governing permissions and 698 +// limitations under the License. 699 + 700 +package loginUI 701 + 702 +import ( 703 + "github.com/matrix-org/gomatrix" 704 + "github.com/therecipe/qt/core" 705 + "github.com/therecipe/qt/gui" 706 + "github.com/therecipe/qt/uitools" 707 + "github.com/therecipe/qt/widgets" 708 +) 709 + 710 +// LoginUI defines the data for the login ui 711 +type LoginUI struct { 712 + widget *widgets.QWidget 713 + cli *gomatrix.Client 714 + window *widgets.QMainWindow 715 + windowWidth int 716 + windowHeight int 717 +} 718 + 719 +// NewLoginUI gives you a MainUI struct with profiled data 720 +func NewLoginUI(windowWidth, windowHeight int, window *widgets.QMainWindow) (loginUI *LoginUI) { 721 + loginUI = &LoginUI{ 722 + windowWidth: windowWidth, 723 + windowHeight: windowHeight, 724 + window: window, 725 + } 726 + return 727 +} 728 + 729 +// SetCli sets the gomatrix Client for the LoginUI 730 +func (m *LoginUI) SetCli(cli *gomatrix.Client) { 731 + m.cli = cli 732 +} 733 + 734 +// GetWidget returns the QWidget of the LoginUI 735 +func (m *LoginUI) GetWidget() (widget *widgets.QWidget) { 736 + return m.widget 737 +} 738 + 739 +// NewUI prepares the new UI 740 +func (m *LoginUI) NewUI() error { 741 + m.widget = widgets.NewQWidget(nil, 0) 742 + 743 + var loader = uitools.NewQUiLoader(nil) 744 + var file = core.NewQFile2(":/qml/ui/login.ui") 745 + 746 + file.Open(core.QIODevice__ReadOnly) 747 + mainWidget := loader.Load(file, m.widget) 748 + file.Close() 749 + 750 + var layout = widgets.NewQHBoxLayout() 751 + m.window.SetLayout(layout) 752 + layout.InsertWidget(0, mainWidget, 0, core.Qt__AlignTop|core.Qt__AlignLeft) 753 + layout.SetSpacing(0) 754 + layout.SetContentsMargins(0, 0, 0, 0) 755 + 756 + m.widget.ConnectResizeEvent(func(event *gui.QResizeEvent) { 757 + mainWidget.Resize(event.Size()) 758 + event.Accept() 759 + }) 760 + 761 + return nil 762 +} 763 diff --git a/pkg/mainUI/mainUI.go b/pkg/mainUI/mainUI.go 764 index 7fcaaf9..a8cddc3 100644 765 --- a/pkg/mainUI/mainUI.go 766 +++ b/pkg/mainUI/mainUI.go 767 @@ -1,3 +1,17 @@ 768 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 769 +// 770 +// Licensed under the Apache License, Version 2.0 (the "License"); 771 +// you may not use this file except in compliance with the License. 772 +// You may obtain a copy of the License at 773 +// 774 +// http://www.apache.org/licenses/LICENSE-2.0 775 +// 776 +// Unless required by applicable law or agreed to in writing, software 777 +// distributed under the License is distributed on an "AS IS" BASIS, 778 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 779 +// See the License for the specific language governing permissions and 780 +// limitations under the License. 781 + 782 package mainUI 783 784 import ( 785 diff --git a/pkg/matrix/dataTypes.go b/pkg/matrix/dataTypes.go 786 index 8d30e68..a010373 100644 787 --- a/pkg/matrix/dataTypes.go 788 +++ b/pkg/matrix/dataTypes.go 789 @@ -1,3 +1,17 @@ 790 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 791 +// 792 +// Licensed under the Apache License, Version 2.0 (the "License"); 793 +// you may not use this file except in compliance with the License. 794 +// You may obtain a copy of the License at 795 +// 796 +// http://www.apache.org/licenses/LICENSE-2.0 797 +// 798 +// Unless required by applicable law or agreed to in writing, software 799 +// distributed under the License is distributed on an "AS IS" BASIS, 800 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 801 +// See the License for the specific language governing permissions and 802 +// limitations under the License. 803 + 804 package matrix 805 806 import ( 807 @@ -9,8 +23,15 @@ import ( 808 type User interface { 809 SetCli(cli *gomatrix.Client) 810 SetMXID(id string) 811 + SetDisplayName(roomID string, name string) 812 + SetAvatar(roomID string, avatar []byte) 813 + 814 + GetMXID() string 815 GetDisplayName(roomID string) (string, error) 816 - GetAvatar(roomID string) (string, error) 817 + GetAvatar(roomID string) ([]byte, error) 818 + GetCli() (cli *gomatrix.Client) 819 + 820 + //Implement MarshalJSON() (b []byte, e error) as in http://gregtrowbridge.com/golang-json-serialization-with-interfaces/ to support json 821 } 822 823 // Room defines a Interface to allow multiple Room type Implementations 824 @@ -18,11 +39,20 @@ type Room interface { 825 // Handled using global "own User" 826 //SetCli(cli *gomatrix.Client) 827 SetRoomID(id string) 828 - SetRoomAliases(aliases map[int64]string) 829 + SetRoomAliases(aliases []string) 830 + SetName(name string) 831 + SetAvatar(avatar []byte) 832 + SetTopic(topic string) 833 + SetMessages(messages []Message) 834 + 835 + GetRoomID() string 836 + GetRoomAliases() []string 837 GetName() (string, error) 838 - GetAvatar() (string, error) 839 + GetAvatar() ([]byte, error) 840 GetTopic() (string, error) 841 - GetMessages() (map[string]Message, error) 842 + GetMessages() []Message 843 + 844 + //Implement MarshalJSON() (b []byte, e error) as in http://gregtrowbridge.com/golang-json-serialization-with-interfaces/ to support json 845 } 846 847 // Message defines a Interface to allow multiple Message type Implementations 848 @@ -34,5 +64,14 @@ type Message interface { 849 SetAuthorMXID(mxid string) 850 SetMessage(message string) 851 SetTimestamp(ts *time.Time) 852 + 853 + GetEventID() (id string) 854 + GetEvent() (event *gomatrix.Event) 855 + GetAuthorMXID() (mxid string) 856 + GetMessage() (message string) 857 + GetTimestamp() (ts *time.Time) 858 + 859 Show() error 860 + 861 + //Implement MarshalJSON() (b []byte, e error) as in http://gregtrowbridge.com/golang-json-serialization-with-interfaces/ to support json 862 } 863 diff --git a/pkg/matrix/messages/message.go b/pkg/matrix/messages/message.go 864 new file mode 100644 865 index 0000000..186fdda 866 --- /dev/null 867 +++ b/pkg/matrix/messages/message.go 868 @@ -0,0 +1,85 @@ 869 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 870 +// 871 +// Licensed under the Apache License, Version 2.0 (the "License"); 872 +// you may not use this file except in compliance with the License. 873 +// You may obtain a copy of the License at 874 +// 875 +// http://www.apache.org/licenses/LICENSE-2.0 876 +// 877 +// Unless required by applicable law or agreed to in writing, software 878 +// distributed under the License is distributed on an "AS IS" BASIS, 879 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 880 +// See the License for the specific language governing permissions and 881 +// limitations under the License. 882 + 883 +package messages 884 + 885 +import ( 886 + "github.com/matrix-org/gomatrix" 887 + "time" 888 +) 889 + 890 +// Message holds the needed Message data and allows to work with that. It gets normally loaded from the cache 891 +type Message struct { 892 + eventID string 893 + event *gomatrix.Event 894 + authorID string 895 + text string 896 + timestamp *time.Time 897 +} 898 + 899 +// SetEventID adds the eventID to the current Message 900 +func (m *Message) SetEventID(id string) { 901 + m.eventID = id 902 +} 903 + 904 +// SetEvent adds the gomatrix Event to the current Message 905 +func (m *Message) SetEvent(event *gomatrix.Event) { 906 + m.event = event 907 +} 908 + 909 +// SetAuthorMXID adds the author MXID to the current Message 910 +func (m *Message) SetAuthorMXID(mxid string) { 911 + m.authorID = mxid 912 +} 913 + 914 +// SetMessage adds the message Text to the current Message 915 +func (m *Message) SetMessage(message string) { 916 + m.text = message 917 +} 918 + 919 +// SetTimestamp adds the Timestamp to the current Message 920 +func (m *Message) SetTimestamp(ts *time.Time) { 921 + m.timestamp = ts 922 +} 923 + 924 +// GetEventID returns the event ID from the current Message 925 +func (m *Message) GetEventID() (id string) { 926 + return m.eventID 927 +} 928 + 929 +// GetEvent returns the gomatrix event from the current Message 930 +func (m *Message) GetEvent() (event *gomatrix.Event) { 931 + return m.event 932 +} 933 + 934 +// GetAuthorMXID returns the authors mxid from the current Message 935 +func (m *Message) GetAuthorMXID() (mxid string) { 936 + return m.authorID 937 +} 938 + 939 +// GetMessage returns the text from the current Message 940 +func (m *Message) GetMessage() (message string) { 941 + return m.text 942 +} 943 + 944 +// GetTimestamp returns the timestamp from the current Message 945 +func (m *Message) GetTimestamp() (ts *time.Time) { 946 + return m.timestamp 947 +} 948 + 949 +// Show adds the current Message to the UI 950 +// TODO implement it 951 +func (m *Message) Show() error { 952 + return nil 953 +} 954 diff --git a/pkg/matrix/rooms/room.go b/pkg/matrix/rooms/room.go 955 new file mode 100644 956 index 0000000..9d884ce 957 --- /dev/null 958 +++ b/pkg/matrix/rooms/room.go 959 @@ -0,0 +1,145 @@ 960 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 961 +// 962 +// Licensed under the Apache License, Version 2.0 (the "License"); 963 +// you may not use this file except in compliance with the License. 964 +// You may obtain a copy of the License at 965 +// 966 +// http://www.apache.org/licenses/LICENSE-2.0 967 +// 968 +// Unless required by applicable law or agreed to in writing, software 969 +// distributed under the License is distributed on an "AS IS" BASIS, 970 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 971 +// See the License for the specific language governing permissions and 972 +// limitations under the License. 973 + 974 +package rooms 975 + 976 +import ( 977 + "github.com/Nordgedanken/Morpheusv2/pkg/matrix" 978 + "github.com/Nordgedanken/Morpheusv2/pkg/util" 979 + "github.com/matrix-org/gomatrix" 980 + "strings" 981 +) 982 + 983 +// Room holds the needed Room data and allows to work with that. It gets normally loaded from the cache 984 +type Room struct { 985 + id string 986 + aliases []string 987 + name string 988 + avatar []byte 989 + topic string 990 + messages []matrix.Message 991 +} 992 + 993 +// SetRoomID adds the roomID to the current Room 994 +func (r *Room) SetRoomID(id string) { 995 + r.id = id 996 +} 997 + 998 +// SetRoomAliases adds the aliases to the current Room 999 +func (r *Room) SetRoomAliases(aliases []string) { 1000 + r.aliases = aliases 1001 +} 1002 + 1003 +// SetName adds the name to the current Room 1004 +func (r *Room) SetName(name string) { 1005 + r.name = name 1006 +} 1007 + 1008 +// SetAvatar adds the avatar to the current Room 1009 +func (r *Room) SetAvatar(avatar []byte) { 1010 + r.avatar = avatar 1011 +} 1012 + 1013 +// SetTopic adds the topic to the current Room 1014 +func (r *Room) SetTopic(topic string) { 1015 + r.topic = topic 1016 +} 1017 + 1018 +// SetMessages adds the messages to the current Room 1019 +func (r *Room) SetMessages(messages []matrix.Message) { 1020 + r.messages = messages 1021 +} 1022 + 1023 +// GetRoomID returns the room ID from the current Room 1024 +func (r *Room) GetRoomID() string { 1025 + return r.id 1026 +} 1027 + 1028 +// GetRoomAliases returns the room aliases from the current Room 1029 +func (r *Room) GetRoomAliases() []string { 1030 + return r.aliases 1031 +} 1032 + 1033 +// GetName returns the name from the current Room 1034 +func (r *Room) GetName() (string, error) { 1035 + if r.name == "" { 1036 + type RespRoomName struct { 1037 + Name string `json:"name"` 1038 + } 1039 + resp := &RespRoomName{} 1040 + err := util.User.GetCli().StateEvent(r.id, "m.room.name", "", resp) 1041 + if err != nil { 1042 + return "", err 1043 + } 1044 + r.name = resp.Name 1045 + } 1046 + return r.name, nil 1047 +} 1048 + 1049 +// GetAvatar returns the avatar from the current Room 1050 +func (r *Room) GetAvatar() ([]byte, error) { 1051 + if r.avatar == nil { 1052 + resp := &gomatrix.Event{} 1053 + err := util.User.GetCli().StateEvent(r.id, "m.room.avatar", "", resp) 1054 + if err != nil { 1055 + return nil, err 1056 + } 1057 + var avatar []byte 1058 + value, exists := resp.Content["url"] 1059 + if !exists { 1060 + return nil, nil 1061 + } 1062 + url, ok := value.(string) 1063 + if !ok { 1064 + return nil, nil 1065 + } 1066 + split := strings.Split(url, "/") 1067 + servername := strings.TrimPrefix(split[0], "mxc://") 1068 + mediaID := split[1] 1069 + mediaURL := util.User.GetCli().BuildBaseURL("_matrix/media/r0/download", servername, mediaID) 1070 + avatar, err = util.User.GetCli().MakeRequest("GET", mediaURL, nil, nil) 1071 + if err != nil { 1072 + return nil, err 1073 + } 1074 + r.avatar = avatar 1075 + } 1076 + return r.avatar, nil 1077 +} 1078 + 1079 +// GetTopic returns the topic from the current Room 1080 +func (r *Room) GetTopic() (string, error) { 1081 + if r.topic == "" { 1082 + resp := &gomatrix.Event{} 1083 + err := util.User.GetCli().StateEvent(r.id, "m.room.topic", "", resp) 1084 + if err != nil { 1085 + return "", err 1086 + } 1087 + value, exists := resp.Content["topic"] 1088 + if !exists { 1089 + return "", nil 1090 + } 1091 + topic, ok := value.(string) 1092 + if !ok { 1093 + return "", nil 1094 + } 1095 + r.topic = topic 1096 + } 1097 + return r.topic, nil 1098 +} 1099 + 1100 +// GetMessages returns the messages from the current Room 1101 +func (r *Room) GetMessages() []matrix.Message { 1102 + // TODO Lazy load from DB 1103 + return r.messages 1104 +} 1105 diff --git a/pkg/matrix/users/user.go b/pkg/matrix/users/user.go 1106 new file mode 100644 1107 index 0000000..8cee5cf 1108 --- /dev/null 1109 +++ b/pkg/matrix/users/user.go 1110 @@ -0,0 +1,127 @@ 1111 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 1112 +// 1113 +// Licensed under the Apache License, Version 2.0 (the "License"); 1114 +// you may not use this file except in compliance with the License. 1115 +// You may obtain a copy of the License at 1116 +// 1117 +// http://www.apache.org/licenses/LICENSE-2.0 1118 +// 1119 +// Unless required by applicable law or agreed to in writing, software 1120 +// distributed under the License is distributed on an "AS IS" BASIS, 1121 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1122 +// See the License for the specific language governing permissions and 1123 +// limitations under the License. 1124 + 1125 +package users 1126 + 1127 +import ( 1128 + "github.com/Nordgedanken/Morpheusv2/pkg/util" 1129 + "github.com/matrix-org/gomatrix" 1130 + "strings" 1131 +) 1132 + 1133 +// User holds the needed User data and allows to work with that. It gets normally loaded from the cache 1134 +type User struct { 1135 + cli *gomatrix.Client 1136 + mxid string 1137 + defaultDisplayName string 1138 + displayName map[string]string 1139 + defaultAvatar []byte 1140 + avatar map[string][]byte 1141 +} 1142 + 1143 +// SetCli adds the gomatrix.Client to the current User. This only happens if the User is the current User aka the one that logged into the client. 1144 +func (u *User) SetCli(cli *gomatrix.Client) { 1145 + u.cli = cli 1146 +} 1147 + 1148 +// SetMXID adds the mxid to the current User 1149 +func (u *User) SetMXID(id string) { 1150 + u.mxid = id 1151 +} 1152 + 1153 +// SetDisplayName adds the displayName to the current User 1154 +func (u *User) SetDisplayName(roomID string, name string) { 1155 + if roomID == "" { 1156 + u.defaultDisplayName = name 1157 + } else { 1158 + if u.displayName == nil { 1159 + u.displayName = make(map[string]string) 1160 + } 1161 + u.displayName[roomID] = name 1162 + } 1163 +} 1164 + 1165 +// SetAvatar adds the avatar to the current User 1166 +func (u *User) SetAvatar(roomID string, avatar []byte) { 1167 + if roomID == "" { 1168 + u.defaultAvatar = avatar 1169 + } else { 1170 + if u.avatar == nil { 1171 + u.avatar = make(map[string][]byte) 1172 + } 1173 + u.avatar[roomID] = avatar 1174 + } 1175 +} 1176 + 1177 +// GetMXID returns the mxid from the current User 1178 +func (u *User) GetMXID() string { 1179 + return u.mxid 1180 +} 1181 + 1182 +// GetDisplayName returns the displayName from the current User 1183 +func (u *User) GetDisplayName(roomID string) (string, error) { 1184 + if roomID == "" { 1185 + if u.defaultDisplayName == "" { 1186 + resp, err := util.User.GetCli().GetDisplayName(u.mxid) 1187 + if err != nil { 1188 + return "", err 1189 + } 1190 + u.defaultDisplayName = resp.DisplayName 1191 + } 1192 + return u.defaultDisplayName, nil 1193 + } 1194 + // TODO get Membership Event from Room instead returning default directly 1195 + if u.displayName[roomID] == "" { 1196 + return u.defaultDisplayName, nil 1197 + } 1198 + return u.displayName[roomID], nil 1199 +} 1200 + 1201 +// GetAvatar returns the avatar from the current User 1202 +func (u *User) GetAvatar(roomID string) ([]byte, error) { 1203 + if roomID == "" { 1204 + if u.defaultAvatar == nil { 1205 + urlPath := util.User.GetCli().BuildURL("profile", u.mxid, "avatar_url") 1206 + s := struct { 1207 + AvatarURL string `json:"avatar_url"` 1208 + }{} 1209 + 1210 + _, err := util.User.GetCli().MakeRequest("GET", urlPath, nil, &s) 1211 + if err != nil { 1212 + return nil, err 1213 + } 1214 + 1215 + split := strings.Split(s.AvatarURL, "/") 1216 + servername := strings.TrimPrefix(split[0], "mxc://") 1217 + mediaID := split[1] 1218 + mediaURL := util.User.GetCli().BuildBaseURL("_matrix/media/r0/download", servername, mediaID) 1219 + avatar, err := util.User.GetCli().MakeRequest("GET", mediaURL, nil, nil) 1220 + if err != nil { 1221 + return nil, err 1222 + } 1223 + u.defaultAvatar = avatar 1224 + } 1225 + return u.defaultAvatar, nil 1226 + } 1227 + // TODO get Membership Event from Room instead returning default directly 1228 + if u.avatar[roomID] == nil { 1229 + return u.defaultAvatar, nil 1230 + } 1231 + return u.avatar[roomID], nil 1232 +} 1233 + 1234 +// GetCli returns the gomatrix.Client from the current User 1235 +func (u *User) GetCli() *gomatrix.Client { 1236 + return u.cli 1237 +} 1238 diff --git a/pkg/util/vars.go b/pkg/util/vars.go 1239 new file mode 100644 1240 index 0000000..7325755 1241 --- /dev/null 1242 +++ b/pkg/util/vars.go 1243 @@ -0,0 +1,26 @@ 1244 +// Copyright © 2018 MTRNord <info@nordgedanken.de> 1245 +// 1246 +// Licensed under the Apache License, Version 2.0 (the "License"); 1247 +// you may not use this file except in compliance with the License. 1248 +// You may obtain a copy of the License at 1249 +// 1250 +// http://www.apache.org/licenses/LICENSE-2.0 1251 +// 1252 +// Unless required by applicable law or agreed to in writing, software 1253 +// distributed under the License is distributed on an "AS IS" BASIS, 1254 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1255 +// See the License for the specific language governing permissions and 1256 +// limitations under the License. 1257 + 1258 +package util 1259 + 1260 +import ( 1261 + "github.com/Nordgedanken/Morpheusv2/pkg/db" 1262 + "github.com/Nordgedanken/Morpheusv2/pkg/matrix" 1263 +) 1264 + 1265 +// DB holds the main pointer to the Database 1266 +var DB db.DB 1267 + 1268 +// User holds the Current User 1269 +var User matrix.User