morpheusv2.meta

Issues/PRs archive for Nordgedanken/Morpheusv2
git clone git://archive.git.mtrnord.blog/Nordgedanken/morpheusv2.meta.git
Log | Files | Refs

6.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, &timestamp, &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(&timestamp)
    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