morpheusv2.meta

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

commit cff8c0ee1d3d8e404dc480392e5e6c6e8186949e
Author: Phorge Migration <migration@localhost>
Date:   Tue, 21 Jul 2026 18:24:31 +0200

Archive issues/PRs export for Nordgedanken/Morpheusv2

Diffstat:
Aissues/5.json | 16++++++++++++++++
Aissues/5.md | 12++++++++++++
Aissues/9.json | 18++++++++++++++++++
Aissues/9.md | 18++++++++++++++++++
Apulls/1.diff | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apulls/1.json | 22++++++++++++++++++++++
Apulls/1.md | 15+++++++++++++++
Apulls/10.diff | 22++++++++++++++++++++++
Apulls/10.json | 18++++++++++++++++++
Apulls/10.md | 19+++++++++++++++++++
Apulls/2.diff | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apulls/2.json | 18++++++++++++++++++
Apulls/2.md | 13+++++++++++++
Apulls/3.diff | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apulls/3.json | 18++++++++++++++++++
Apulls/3.md | 13+++++++++++++
Apulls/4.diff | 464+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apulls/4.json | 22++++++++++++++++++++++
Apulls/4.md | 15+++++++++++++++
Apulls/6.diff | 1269+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apulls/6.json | 22++++++++++++++++++++++
Apulls/6.md | 15+++++++++++++++
Apulls/7.diff | 1269+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apulls/7.json | 18++++++++++++++++++
Apulls/7.md | 13+++++++++++++
Apulls/8.diff | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apulls/8.json | 20++++++++++++++++++++
Apulls/8.md | 14++++++++++++++
28 files changed, 3901 insertions(+), 0 deletions(-)

diff --git a/issues/5.json b/issues/5.json @@ -0,0 +1,16 @@ +{ + "number": 5, + "title": "Use migrate for the DB tables to make sure we wont run in non true errors because I changed a DB table", + "state": "open", + "author": "MTRNord", + "created_at": "2018-05-05T22:39:35Z", + "closed_at": null, + "labels": [ + "enhancement" + ], + "assignees": [ + "MTRNord" + ], + "body": "https://github.com/mattes/migrate", + "comments": [] +} diff --git a/issues/5.md b/issues/5.md @@ -0,0 +1,12 @@ +# #5 Use migrate for the DB tables to make sure we wont run in non true errors because I changed a DB table + +- **State:** open +- **Author:** @MTRNord +- **Created:** 2018-05-05T22:39:35Z +- **Labels:** enhancement +- **Assignees:** @MTRNord + +--- + +https://github.com/mattes/migrate + diff --git a/issues/9.json b/issues/9.json @@ -0,0 +1,18 @@ +{ + "number": 9, + "title": "Make sure we use qimage instead qpixmap ", + "state": "closed", + "author": "MTRNord", + "created_at": "2018-05-06T06:42:59Z", + "closed_at": "2018-05-09T19:24:19Z", + "labels": [], + "assignees": [], + "body": "", + "comments": [ + { + "author": "MTRNord", + "created_at": "2018-05-06T06:44:23Z", + "body": "https://stackoverflow.com/a/4474570/4929236" + } + ] +} diff --git a/issues/9.md b/issues/9.md @@ -0,0 +1,18 @@ +# #9 Make sure we use qimage instead qpixmap + +- **State:** closed +- **Author:** @MTRNord +- **Created:** 2018-05-06T06:42:59Z +- **Closed:** 2018-05-09T19:24:19Z + +--- + +_No description._ + + +## Comments + +### @MTRNord — 2018-05-06T06:44:23Z + +https://stackoverflow.com/a/4474570/4929236 + diff --git a/pulls/1.diff b/pulls/1.diff @@ -0,0 +1,156 @@ +diff --git a/.circleci/config.yml b/.circleci/config.yml +index 4fee27f..5f9a38f 100644 +--- a/.circleci/config.yml ++++ b/.circleci/config.yml +@@ -41,7 +41,7 @@ jobs: + - run: + name: Run Build + working_directory: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/ +- command: $GOPATH/bin/qtdeploy build linux ++ command: /home/user/work/bin/qtdeploy build desktop + - run: + name: Prepare Deb Generating + working_directory: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/ +@@ -86,7 +86,7 @@ jobs: + - run: + name: Run Build + working_directory: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/ +- command: $GOPATH/bin/qtdeploy build windows ++ command: /home/user/work/bin/qtdeploy build windows + - store_artifacts: + path: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/deploy/windows/Morpheusv2.exe + destination: Morpheusv2.exe +diff --git a/Gopkg.lock b/Gopkg.lock +index 13077c2..ec45e23 100644 +--- a/Gopkg.lock ++++ b/Gopkg.lock +@@ -25,15 +25,9 @@ + revision = "583c0c0531f06d5278b7d917446061adc344b5cd" + version = "v1.0.1" + +-[[projects]] +- branch = "master" +- name = "github.com/therecipe/qt" +- packages = [".","core","gui","widgets"] +- revision = "7038382d6c7bb5fd3957df56bbedf8ec4ca6b67c" +- + [solve-meta] + analyzer-name = "dep" + analyzer-version = 1 +- inputs-digest = "a82e2ac4eccca051143202632fee6ebf07b015e82f3d04c4bc426be93aab708b" ++ inputs-digest = "9eae52af7d8c49e9a27a1863ba05582acb167fd5a5ce5bf23b6eb9288a20d0c2" + solver-name = "gps-cdcl" + solver-version = 1 +diff --git a/Gopkg.toml b/Gopkg.toml +index a975b22..b1ccb25 100644 +--- a/Gopkg.toml ++++ b/Gopkg.toml +@@ -21,10 +21,8 @@ + # version = "2.4.0" + + +-[[constraint]] +- branch = "master" +- name = "github.com/shibukawa/configdir" ++ignored = ["github.com/therecipe/qt/*"] + + [[constraint]] + branch = "master" +- name = "github.com/therecipe/qt" ++ name = "github.com/shibukawa/configdir" +\ No newline at end of file +diff --git a/cmd/root.go b/cmd/root.go +index 3374e09..61a0ac4 100644 +--- a/cmd/root.go ++++ b/cmd/root.go +@@ -22,8 +22,6 @@ import ( + "github.com/spf13/cobra" + ) + +-var cfgFile string +- + // rootCmd represents the base command when called without any subcommands + var rootCmd = &cobra.Command{ + Use: "Morpheusv2", +@@ -48,5 +46,4 @@ func Execute() { + fmt.Println(err) + os.Exit(1) + } +- os.Exit(0) + } +diff --git a/deb.json b/deb.json +index 767176a..f710e5e 100644 +--- a/deb.json ++++ b/deb.json +@@ -1,7 +1,7 @@ + { + "name": "Morpheusv2", + "maintainer": "MTRNord <info@nordgedanken.de>", +- "version": "0.0.1", ++ "version": "0.1.0", + "arch": "amd64", + "files": [ + { +@@ -50,7 +50,7 @@ + "description":"A Matrix client written in Go-QT ", + "generic-name":"Matrix Client", + "exec":"/usr/bin/Morpheusv2.sh", +- "icon":"qml/resources/logos/MorpheusBig.png", ++ "icon":"pkg/qml/resources/logos/MorpheusBig.png", + "type":"Application", + "keywords":"matrix;Morpheusv2", + "startup-notify": false, +diff --git a/linter.json b/linter.json +new file mode 100644 +index 0000000..2b2b1f4 +--- /dev/null ++++ b/linter.json +@@ -0,0 +1,22 @@ ++{ ++ "Vendor": true, ++ "Cyclo": 12, ++ "Deadline": "5m", ++ "Enable": [ ++ "vetshadow", ++ "deadcode", ++ "gocyclo", ++ "golint", ++ "varcheck", ++ "structcheck", ++ "ineffassign", ++ "gas", ++ "misspell", ++ "unparam", ++ "errcheck", ++ "vet", ++ "megacheck", ++ "goconst", ++ "maligned" ++ ] ++} +\ No newline at end of file +diff --git a/pkg/app/main.go b/pkg/app/main.go +index 5caabde..43d28a6 100644 +--- a/pkg/app/main.go ++++ b/pkg/app/main.go +@@ -24,6 +24,7 @@ import ( + "path/filepath" + ) + ++// Start prepares the Main QT Window and opens it + func Start(args []string) error { + log.Println("Starting Morpheus v2") + +diff --git a/pkg/mainThreadHelper.go b/pkg/mainThreadHelper.go +index 32b4d1a..4311a21 100644 +--- a/pkg/mainThreadHelper.go ++++ b/pkg/mainThreadHelper.go +@@ -27,7 +27,7 @@ func Main() { + // queue of work to run in main thread. + var mainfunc = make(chan func()) + +-// do runs f on the main thread. ++// Do runs f on the main thread. + func Do(f func()) { + done := make(chan bool, 1) + mainfunc <- func() { diff --git a/pulls/1.json b/pulls/1.json @@ -0,0 +1,22 @@ +{ + "number": 1, + "title": "Fix CI building", + "state": "merged", + "diff_file": "1.diff", + "author": "MTRNord", + "created_at": "2018-05-01T16:21:48Z", + "closed_at": "2018-05-01T16:33:41Z", + "merged_at": "2018-05-01T16:33:41Z", + "base_ref": "master", + "head_ref": "develop", + "labels": [ + "enhancement" + ], + "assignees": [ + "MTRNord" + ], + "requested_reviewers": [], + "body": "", + "comments": [], + "review_comments": [] +} diff --git a/pulls/1.md b/pulls/1.md @@ -0,0 +1,15 @@ +# PR #1 Fix CI building + +- **Status:** merged +- **Author:** @MTRNord +- **Created:** 2018-05-01T16:21:48Z +- **Branch:** develop → master +- **Merged:** 2018-05-01T16:33:41Z +- **Labels:** enhancement +- **Assignees:** @MTRNord +- **Diff:** [1.diff](./1.diff) + +--- + +_No description._ + diff --git a/pulls/10.diff b/pulls/10.diff @@ -0,0 +1,22 @@ +diff --git a/README.md b/README.md +index efb62e7..e05ff01 100644 +--- a/README.md ++++ b/README.md +@@ -1,5 +1,6 @@ + # Morpheus v2 + [![CircleCI branch](https://img.shields.io/circleci/project/github/Nordgedanken/Morpheusv2/master.svg)](https://circleci.com/gh/Nordgedanken/Morpheusv2) ++[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FNordgedanken%2FMorpheusv2.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FNordgedanken%2FMorpheusv2?ref=badge_shield) + + [![Github All Releases](https://img.shields.io/github/downloads/Nordgedanken/Morpheusv2/total.svg)]() + +@@ -35,5 +36,8 @@ We use [SemVer](http://semver.org/) for versioning. For the versions available, + ## License + This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details + ++ ++[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FNordgedanken%2FMorpheusv2.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FNordgedanken%2FMorpheusv2?ref=badge_large) ++ + ## Acknowledgments +-* Inspired by [nheko](http://github.com/mujx/nheko) ++* Inspired by [nheko](http://github.com/mujx/nheko) +\ No newline at end of file diff --git a/pulls/10.json b/pulls/10.json @@ -0,0 +1,18 @@ +{ + "number": 10, + "title": "Add license scan report and status", + "state": "open", + "diff_file": "10.diff", + "author": "fossabot", + "created_at": "2018-05-12T22:37:04Z", + "closed_at": null, + "merged_at": null, + "base_ref": "master", + "head_ref": "master", + "labels": [], + "assignees": [], + "requested_reviewers": [], + "body": "Your FOSSA integration was successful! Attached in this PR is a badge and license report to track scan status in your README.\n\nBelow are docs for integrating FOSSA license checks into your CI:\n\n- [CircleCI](https://docs.fossa.io/docs/circleci)\n- [TravisCI](https://docs.fossa.io/docs/travisci)\n- [Jenkins](https://github.com/fossas/fossa-jenkins-plugin)\n- [Other](https://github.com/fossas/fossa-cli)", + "comments": [], + "review_comments": [] +} diff --git a/pulls/10.md b/pulls/10.md @@ -0,0 +1,19 @@ +# PR #10 Add license scan report and status + +- **Status:** open +- **Author:** @fossabot +- **Created:** 2018-05-12T22:37:04Z +- **Branch:** master → master +- **Diff:** [10.diff](./10.diff) + +--- + +Your FOSSA integration was successful! Attached in this PR is a badge and license report to track scan status in your README. + +Below are docs for integrating FOSSA license checks into your CI: + +- [CircleCI](https://docs.fossa.io/docs/circleci) +- [TravisCI](https://docs.fossa.io/docs/travisci) +- [Jenkins](https://github.com/fossas/fossa-jenkins-plugin) +- [Other](https://github.com/fossas/fossa-cli) + diff --git a/pulls/2.diff b/pulls/2.diff @@ -0,0 +1,156 @@ +diff --git a/.circleci/config.yml b/.circleci/config.yml +index 5f9a38f..4fee27f 100644 +--- a/.circleci/config.yml ++++ b/.circleci/config.yml +@@ -41,7 +41,7 @@ jobs: + - run: + name: Run Build + working_directory: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/ +- command: /home/user/work/bin/qtdeploy build desktop ++ command: $GOPATH/bin/qtdeploy build linux + - run: + name: Prepare Deb Generating + working_directory: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/ +@@ -86,7 +86,7 @@ jobs: + - run: + name: Run Build + working_directory: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/ +- command: /home/user/work/bin/qtdeploy build windows ++ command: $GOPATH/bin/qtdeploy build windows + - store_artifacts: + path: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/deploy/windows/Morpheusv2.exe + destination: Morpheusv2.exe +diff --git a/Gopkg.lock b/Gopkg.lock +index ec45e23..13077c2 100644 +--- a/Gopkg.lock ++++ b/Gopkg.lock +@@ -25,9 +25,15 @@ + revision = "583c0c0531f06d5278b7d917446061adc344b5cd" + version = "v1.0.1" + ++[[projects]] ++ branch = "master" ++ name = "github.com/therecipe/qt" ++ packages = [".","core","gui","widgets"] ++ revision = "7038382d6c7bb5fd3957df56bbedf8ec4ca6b67c" ++ + [solve-meta] + analyzer-name = "dep" + analyzer-version = 1 +- inputs-digest = "9eae52af7d8c49e9a27a1863ba05582acb167fd5a5ce5bf23b6eb9288a20d0c2" ++ inputs-digest = "a82e2ac4eccca051143202632fee6ebf07b015e82f3d04c4bc426be93aab708b" + solver-name = "gps-cdcl" + solver-version = 1 +diff --git a/Gopkg.toml b/Gopkg.toml +index b1ccb25..a975b22 100644 +--- a/Gopkg.toml ++++ b/Gopkg.toml +@@ -21,8 +21,10 @@ + # version = "2.4.0" + + +-ignored = ["github.com/therecipe/qt/*"] ++[[constraint]] ++ branch = "master" ++ name = "github.com/shibukawa/configdir" + + [[constraint]] + branch = "master" +- name = "github.com/shibukawa/configdir" +\ No newline at end of file ++ name = "github.com/therecipe/qt" +diff --git a/cmd/root.go b/cmd/root.go +index 61a0ac4..3374e09 100644 +--- a/cmd/root.go ++++ b/cmd/root.go +@@ -22,6 +22,8 @@ import ( + "github.com/spf13/cobra" + ) + ++var cfgFile string ++ + // rootCmd represents the base command when called without any subcommands + var rootCmd = &cobra.Command{ + Use: "Morpheusv2", +@@ -46,4 +48,5 @@ func Execute() { + fmt.Println(err) + os.Exit(1) + } ++ os.Exit(0) + } +diff --git a/deb.json b/deb.json +index f710e5e..767176a 100644 +--- a/deb.json ++++ b/deb.json +@@ -1,7 +1,7 @@ + { + "name": "Morpheusv2", + "maintainer": "MTRNord <info@nordgedanken.de>", +- "version": "0.1.0", ++ "version": "0.0.1", + "arch": "amd64", + "files": [ + { +@@ -50,7 +50,7 @@ + "description":"A Matrix client written in Go-QT ", + "generic-name":"Matrix Client", + "exec":"/usr/bin/Morpheusv2.sh", +- "icon":"pkg/qml/resources/logos/MorpheusBig.png", ++ "icon":"qml/resources/logos/MorpheusBig.png", + "type":"Application", + "keywords":"matrix;Morpheusv2", + "startup-notify": false, +diff --git a/linter.json b/linter.json +deleted file mode 100644 +index 2b2b1f4..0000000 +--- a/linter.json ++++ /dev/null +@@ -1,22 +0,0 @@ +-{ +- "Vendor": true, +- "Cyclo": 12, +- "Deadline": "5m", +- "Enable": [ +- "vetshadow", +- "deadcode", +- "gocyclo", +- "golint", +- "varcheck", +- "structcheck", +- "ineffassign", +- "gas", +- "misspell", +- "unparam", +- "errcheck", +- "vet", +- "megacheck", +- "goconst", +- "maligned" +- ] +-} +\ No newline at end of file +diff --git a/pkg/app/main.go b/pkg/app/main.go +index 43d28a6..5caabde 100644 +--- a/pkg/app/main.go ++++ b/pkg/app/main.go +@@ -24,7 +24,6 @@ import ( + "path/filepath" + ) + +-// Start prepares the Main QT Window and opens it + func Start(args []string) error { + log.Println("Starting Morpheus v2") + +diff --git a/pkg/mainThreadHelper.go b/pkg/mainThreadHelper.go +index 4311a21..32b4d1a 100644 +--- a/pkg/mainThreadHelper.go ++++ b/pkg/mainThreadHelper.go +@@ -27,7 +27,7 @@ func Main() { + // queue of work to run in main thread. + var mainfunc = make(chan func()) + +-// Do runs f on the main thread. ++// do runs f on the main thread. + func Do(f func()) { + done := make(chan bool, 1) + mainfunc <- func() { diff --git a/pulls/2.json b/pulls/2.json @@ -0,0 +1,18 @@ +{ + "number": 2, + "title": "Revert \"Fix CI building\"", + "state": "merged", + "diff_file": "2.diff", + "author": "MTRNord", + "created_at": "2018-05-01T16:34:30Z", + "closed_at": "2018-05-01T16:34:55Z", + "merged_at": "2018-05-01T16:34:55Z", + "base_ref": "master", + "head_ref": "revert-1-develop", + "labels": [], + "assignees": [], + "requested_reviewers": [], + "body": "Reverts Nordgedanken/Morpheusv2#1", + "comments": [], + "review_comments": [] +} diff --git a/pulls/2.md b/pulls/2.md @@ -0,0 +1,13 @@ +# PR #2 Revert "Fix CI building" + +- **Status:** merged +- **Author:** @MTRNord +- **Created:** 2018-05-01T16:34:30Z +- **Branch:** revert-1-develop → master +- **Merged:** 2018-05-01T16:34:55Z +- **Diff:** [2.diff](./2.diff) + +--- + +Reverts Nordgedanken/Morpheusv2#1 + diff --git a/pulls/3.diff b/pulls/3.diff @@ -0,0 +1,156 @@ +diff --git a/.circleci/config.yml b/.circleci/config.yml +index 4fee27f..5f9a38f 100644 +--- a/.circleci/config.yml ++++ b/.circleci/config.yml +@@ -41,7 +41,7 @@ jobs: + - run: + name: Run Build + working_directory: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/ +- command: $GOPATH/bin/qtdeploy build linux ++ command: /home/user/work/bin/qtdeploy build desktop + - run: + name: Prepare Deb Generating + working_directory: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/ +@@ -86,7 +86,7 @@ jobs: + - run: + name: Run Build + working_directory: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/ +- command: $GOPATH/bin/qtdeploy build windows ++ command: /home/user/work/bin/qtdeploy build windows + - store_artifacts: + path: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/deploy/windows/Morpheusv2.exe + destination: Morpheusv2.exe +diff --git a/Gopkg.lock b/Gopkg.lock +index 13077c2..ec45e23 100644 +--- a/Gopkg.lock ++++ b/Gopkg.lock +@@ -25,15 +25,9 @@ + revision = "583c0c0531f06d5278b7d917446061adc344b5cd" + version = "v1.0.1" + +-[[projects]] +- branch = "master" +- name = "github.com/therecipe/qt" +- packages = [".","core","gui","widgets"] +- revision = "7038382d6c7bb5fd3957df56bbedf8ec4ca6b67c" +- + [solve-meta] + analyzer-name = "dep" + analyzer-version = 1 +- inputs-digest = "a82e2ac4eccca051143202632fee6ebf07b015e82f3d04c4bc426be93aab708b" ++ inputs-digest = "9eae52af7d8c49e9a27a1863ba05582acb167fd5a5ce5bf23b6eb9288a20d0c2" + solver-name = "gps-cdcl" + solver-version = 1 +diff --git a/Gopkg.toml b/Gopkg.toml +index a975b22..b1ccb25 100644 +--- a/Gopkg.toml ++++ b/Gopkg.toml +@@ -21,10 +21,8 @@ + # version = "2.4.0" + + +-[[constraint]] +- branch = "master" +- name = "github.com/shibukawa/configdir" ++ignored = ["github.com/therecipe/qt/*"] + + [[constraint]] + branch = "master" +- name = "github.com/therecipe/qt" ++ name = "github.com/shibukawa/configdir" +\ No newline at end of file +diff --git a/cmd/root.go b/cmd/root.go +index 3374e09..61a0ac4 100644 +--- a/cmd/root.go ++++ b/cmd/root.go +@@ -22,8 +22,6 @@ import ( + "github.com/spf13/cobra" + ) + +-var cfgFile string +- + // rootCmd represents the base command when called without any subcommands + var rootCmd = &cobra.Command{ + Use: "Morpheusv2", +@@ -48,5 +46,4 @@ func Execute() { + fmt.Println(err) + os.Exit(1) + } +- os.Exit(0) + } +diff --git a/deb.json b/deb.json +index 767176a..f710e5e 100644 +--- a/deb.json ++++ b/deb.json +@@ -1,7 +1,7 @@ + { + "name": "Morpheusv2", + "maintainer": "MTRNord <info@nordgedanken.de>", +- "version": "0.0.1", ++ "version": "0.1.0", + "arch": "amd64", + "files": [ + { +@@ -50,7 +50,7 @@ + "description":"A Matrix client written in Go-QT ", + "generic-name":"Matrix Client", + "exec":"/usr/bin/Morpheusv2.sh", +- "icon":"qml/resources/logos/MorpheusBig.png", ++ "icon":"pkg/qml/resources/logos/MorpheusBig.png", + "type":"Application", + "keywords":"matrix;Morpheusv2", + "startup-notify": false, +diff --git a/linter.json b/linter.json +new file mode 100644 +index 0000000..2b2b1f4 +--- /dev/null ++++ b/linter.json +@@ -0,0 +1,22 @@ ++{ ++ "Vendor": true, ++ "Cyclo": 12, ++ "Deadline": "5m", ++ "Enable": [ ++ "vetshadow", ++ "deadcode", ++ "gocyclo", ++ "golint", ++ "varcheck", ++ "structcheck", ++ "ineffassign", ++ "gas", ++ "misspell", ++ "unparam", ++ "errcheck", ++ "vet", ++ "megacheck", ++ "goconst", ++ "maligned" ++ ] ++} +\ No newline at end of file +diff --git a/pkg/app/main.go b/pkg/app/main.go +index 5caabde..43d28a6 100644 +--- a/pkg/app/main.go ++++ b/pkg/app/main.go +@@ -24,6 +24,7 @@ import ( + "path/filepath" + ) + ++// Start prepares the Main QT Window and opens it + func Start(args []string) error { + log.Println("Starting Morpheus v2") + +diff --git a/pkg/mainThreadHelper.go b/pkg/mainThreadHelper.go +index 32b4d1a..4311a21 100644 +--- a/pkg/mainThreadHelper.go ++++ b/pkg/mainThreadHelper.go +@@ -27,7 +27,7 @@ func Main() { + // queue of work to run in main thread. + var mainfunc = make(chan func()) + +-// do runs f on the main thread. ++// Do runs f on the main thread. + func Do(f func()) { + done := make(chan bool, 1) + mainfunc <- func() { diff --git a/pulls/3.json b/pulls/3.json @@ -0,0 +1,18 @@ +{ + "number": 3, + "title": "Fix CI", + "state": "merged", + "diff_file": "3.diff", + "author": "MTRNord", + "created_at": "2018-05-01T16:37:03Z", + "closed_at": "2018-05-01T16:37:18Z", + "merged_at": "2018-05-01T16:37:18Z", + "base_ref": "master", + "head_ref": "develop", + "labels": [], + "assignees": [], + "requested_reviewers": [], + "body": "", + "comments": [], + "review_comments": [] +} diff --git a/pulls/3.md b/pulls/3.md @@ -0,0 +1,13 @@ +# PR #3 Fix CI + +- **Status:** merged +- **Author:** @MTRNord +- **Created:** 2018-05-01T16:37:03Z +- **Branch:** develop → master +- **Merged:** 2018-05-01T16:37:18Z +- **Diff:** [3.diff](./3.diff) + +--- + +_No description._ + diff --git a/pulls/4.diff b/pulls/4.diff @@ -0,0 +1,464 @@ +diff --git a/.circleci/config.yml b/.circleci/config.yml +index 5f9a38f..4f0571c 100644 +--- a/.circleci/config.yml ++++ b/.circleci/config.yml +@@ -21,12 +21,18 @@ jobs: + name: Get Go Dependencies + working_directory: /home/user/work/src/github.com/Nordgedanken/Morpheusv2/ + command: dep ensure ++ - run: ++ name: Setup Code Climate test-reporter ++ command: | ++ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter ++ chmod +x ./cc-test-reporter + - persist_to_workspace: + # Must be an absolute path, or relative path from working_directory + root: /home/user/work/ + # Must be relative path from root + paths: + - src/ ++ - ./cc-test-reporter + build_linux: + docker: + - image: therecipe/qt:linux +diff --git a/Gopkg.lock b/Gopkg.lock +index 6773bcc..7859130 100644 +--- a/Gopkg.lock ++++ b/Gopkg.lock +@@ -7,6 +7,12 @@ + revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75" + version = "v1.0" + ++[[projects]] ++ branch = "master" ++ name = "github.com/matrix-org/gomatrix" ++ packages = ["."] ++ revision = "a7fc80c8060c2544fe5d4dae465b584f8e9b4e27" ++ + [[projects]] + branch = "master" + name = "github.com/shibukawa/configdir" +diff --git a/cmd/root.go b/cmd/root.go +index 61a0ac4..148f65a 100644 +--- a/cmd/root.go ++++ b/cmd/root.go +@@ -19,19 +19,57 @@ import ( + "os" + + "github.com/Nordgedanken/Morpheusv2/pkg/app" ++ dbImpl "github.com/Nordgedanken/Morpheusv2/pkg/db/implementation" ++ "github.com/shibukawa/configdir" + "github.com/spf13/cobra" ++ "io" ++ "log" ++ "path/filepath" + ) + + // rootCmd represents the base command when called without any subcommands + var rootCmd = &cobra.Command{ +- Use: "Morpheusv2", +- Short: "A brief description of your application", +- Long: `A longer description that spans multiple lines and likely contains +-examples and usage of using your application. For example: +- +-Cobra is a CLI library for Go that empowers applications. +-This application is a tool to generate the needed files +-to quickly create a Cobra application.`, ++ Use: "Morpheusv2", ++ PreRunE: func(cmd *cobra.Command, args []string) error { ++ // Init Logs and folders ++ // configdir.New gets the Config Paths that are available on this system ++ configDirs := configdir.New("Nordgedanken", "Morpheusv2") ++ // path holds the global configdir of the system with the log folder appended ++ path := filepath.ToSlash(configDirs.QueryFolders(configdir.Global)[0].Path + "/log/") ++ logFilePath := filepath.ToSlash(path + "main.log") ++ ++ // This checks if the directory is missing and if that's the case to generate the directory ++ if _, StatErr := os.Stat(path); os.IsNotExist(StatErr) { ++ MkdirErr := os.MkdirAll(path, os.ModeDir) ++ if MkdirErr != nil { ++ return MkdirErr ++ } ++ } ++ ++ // os.OpenFile opens the file where the log is supposed to be written to ++ logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) ++ if err != nil { ++ return err ++ } ++ ++ // MultiWriter makes it possible to print log to both log File and console ++ mw := io.MultiWriter(os.Stdout, logFile) ++ ++ // SetOutput tells the log where to write to ++ log.SetOutput(mw) ++ ++ // dbImpl.Init() generates the needed tables if needed before the app starts ++ err = dbImpl.Init() ++ if err != nil { ++ return err ++ } ++ ++ log.Println("DB Set Up") ++ return nil ++ }, ++ // TODO add descriptions ++ Short: "", ++ Long: ``, + // Uncomment the following line if your bare application + // has an action associated with it: + RunE: func(cmd *cobra.Command, args []string) error { +diff --git a/deb.json b/deb.json +index f710e5e..3a72561 100644 +--- a/deb.json ++++ b/deb.json +@@ -50,7 +50,7 @@ + "description":"A Matrix client written in Go-QT ", + "generic-name":"Matrix Client", + "exec":"/usr/bin/Morpheusv2.sh", +- "icon":"pkg/qml/resources/logos/MorpheusBig.png", ++ "icon":"qml/resources/logos/MorpheusBig.png", + "type":"Application", + "keywords":"matrix;Morpheusv2", + "startup-notify": false, +diff --git a/main.go b/main.go +index f305e76..06c10b1 100644 +--- a/main.go ++++ b/main.go +@@ -16,24 +16,18 @@ package main + + import ( + "github.com/Nordgedanken/Morpheusv2/cmd" +- "github.com/Nordgedanken/Morpheusv2/pkg" +- "runtime" ++ "os" ++ "os/signal" ++ "syscall" + ) + +-// Arrange that main.main runs on main thread. +-func init() { +- runtime.LockOSThread() +-} ++var c = make(chan os.Signal, 2) + + func main() { +- go pkg.Do(cmd.Execute) ++ signal.Notify(c, os.Interrupt, syscall.SIGTERM) + go func() { +- for { +- pkg.Do(noop) +- } ++ <-c ++ os.Exit(1) + }() +- +- pkg.Main() ++ cmd.Execute() + } +- +-func noop() {} +diff --git a/pkg/app/main.go b/pkg/app/main.go +index 43d28a6..3832900 100644 +--- a/pkg/app/main.go ++++ b/pkg/app/main.go +@@ -15,28 +15,37 @@ + package app + + import ( +- "github.com/shibukawa/configdir" ++ "github.com/Nordgedanken/Morpheusv2/pkg/mainUI" ++ "github.com/matrix-org/gomatrix" + "github.com/therecipe/qt/core" + "github.com/therecipe/qt/gui" + "github.com/therecipe/qt/widgets" + "log" +- "os" +- "path/filepath" + ) + ++var args []string ++var cli *gomatrix.Client ++var windowHeight = 600 ++var windowWidth = 950 ++var window *widgets.QMainWindow ++ + // Start prepares the Main QT Window and opens it +-func Start(args []string) error { ++func Start(argsArg []string) error { ++ args = argsArg + log.Println("Starting Morpheus v2") + +- // Init Logs and folders +- configDirs := configdir.New("Nordgedanken", "Morpheus") +- if _, StatErr := os.Stat(filepath.ToSlash(configDirs.QueryFolders(configdir.Global)[0].Path) + "/log/"); os.IsNotExist(StatErr) { +- MkdirErr := os.MkdirAll(filepath.ToSlash(configDirs.QueryFolders(configdir.Global)[0].Path)+"/log/", 0700) +- if MkdirErr != nil { +- return MkdirErr +- } +- } ++ initApp() ++ ++ mainUIS := mainUI.NewMainUI(windowWidth, windowHeight, window) ++ SetNewWindow(mainUIS, window) ++ ++ widgets.QApplication_Exec() + ++ return nil ++} ++ ++func initApp() { ++ log.Println("Create QApp") + app := widgets.NewQApplication(len(args), args) + + app.SetAttribute(core.Qt__AA_UseHighDpiPixmaps, true) +@@ -44,22 +53,33 @@ func Start(args []string) error { + app.SetApplicationVersion("0.1.0") + appIcon := gui.NewQIcon5(":/qml/resources/logos/MorpheusBig.png") + app.SetWindowIcon(appIcon) ++ window = widgets.NewQMainWindow(nil, 0) ++ app.SetActiveWindow(window) + +- window := widgets.NewQMainWindow(nil, 0) +- +- windowHeight := 600 +- windowWidth := 950 +- +- desktopApp := widgets.QApplication_Desktop() ++ desktopApp := app.Desktop() + primaryScreen := desktopApp.PrimaryScreen() + screen := desktopApp.Screen(primaryScreen) + windowX := (screen.Width() - windowHeight) / 2 + windowY := (screen.Height() - windowWidth) / 2 + + window.Resize2(windowWidth, windowHeight) +- window.Show() +- + window.Move2(windowX, windowY) + ++ app.ConnectQuit(func() { ++ log.Println("Morpheus closed") ++ }) ++ ++} ++ ++// SetNewWindow loads the new UI into the QMainWindow ++func SetNewWindow(ui ui, window *widgets.QMainWindow) error { ++ ui.SetCli(cli) ++ uiErr := ui.NewUI() ++ if uiErr != nil { ++ return uiErr ++ } ++ ui.GetWidget().Resize2(windowWidth, windowHeight) ++ window.SetCentralWidget(ui.GetWidget()) ++ window.Show() + return nil + } +diff --git a/pkg/app/ui.go b/pkg/app/ui.go +new file mode 100644 +index 0000000..37ced17 +--- /dev/null ++++ b/pkg/app/ui.go +@@ -0,0 +1,12 @@ ++package app ++ ++import ( ++ "github.com/matrix-org/gomatrix" ++ "github.com/therecipe/qt/widgets" ++) ++ ++type ui interface { ++ SetCli(cli *gomatrix.Client) ++ GetWidget() (widget *widgets.QWidget) ++ NewUI() error ++} +diff --git a/pkg/db/db.go b/pkg/db/db.go +new file mode 100644 +index 0000000..0ffaede +--- /dev/null ++++ b/pkg/db/db.go +@@ -0,0 +1,14 @@ ++package db ++ ++import "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++ ++// DB defines a Interface to allow multiple DB Implementations ++type DB interface { ++ SaveRoom(Room matrix.Room) error ++ GetRooms() (rooms map[string]matrix.Room, err error) ++ GetRoom(roomID string) (room matrix.Room, err error) ++ ++ SaveUser(user matrix.User) error ++ GetUsers() (map[string]matrix.User, error) ++ GetCurrentUser() (matrix.User, error) ++} +diff --git a/pkg/db/implementation/db.go b/pkg/db/implementation/db.go +new file mode 100644 +index 0000000..9429d4b +--- /dev/null ++++ b/pkg/db/implementation/db.go +@@ -0,0 +1,51 @@ ++package implementation ++ ++import ( ++ "database/sql" ++ "fmt" ++ _ "github.com/mattn/go-sqlite3" // Go-sqlite3 side effect import needed to use SQLite3 databases ++ "github.com/shibukawa/configdir" ++ "log" ++ "path/filepath" ++) ++ ++var db *sql.DB ++ ++// Init prepares the DB by opening it and creating the required tables if needed ++// TODO: Make part of the interface ++func Init() (err error) { ++ log.Println("Start setting up DB") ++ var openErr error ++ ++ // Open the data.db file. It will be created if it doesn't exist. ++ configDirs := configdir.New("Nordgedanken", "Morpheusv2") ++ filePath := filepath.ToSlash(configDirs.QueryFolders(configdir.Global)[0].Path) ++ ++ log.Println("DBFilePath: ", filePath+"/data.db") ++ db, openErr = sql.Open("sqlite3", filePath+"/data.db") ++ if openErr != nil { ++ err = openErr ++ return ++ } ++ ++ log.Println("Creating DB Tables if needed") ++ createTables := `CREATE TABLE IF NOT EXISTS users (id integer not null primary key, display_name text, avatar text); ++ CREATE TABLE IF NOT EXISTS messages (id integer not null primary key, author text, message text, timestamp text, pure_event text); ++ CREATE TABLE IF NOT EXISTS rooms (id integer not null primary key, room_aliases text, room_id text, room_name text, room_avatar text, room_topic text, room_messages text); ++ ` ++ _, execErr := db.Exec(createTables) ++ if execErr != nil { ++ err = fmt.Errorf("DB EXEC ERR: %s", execErr) ++ return ++ } ++ log.Println("Finished setting DB Setup") ++ return ++} ++ ++// Open returns the in Init() created db variable ++func Open() *sql.DB { ++ if db != nil { ++ return db ++ } ++ return nil ++} +diff --git a/pkg/mainUI/mainUI.go b/pkg/mainUI/mainUI.go +new file mode 100644 +index 0000000..7fcaaf9 +--- /dev/null ++++ b/pkg/mainUI/mainUI.go +@@ -0,0 +1,63 @@ ++package mainUI ++ ++import ( ++ "github.com/matrix-org/gomatrix" ++ "github.com/therecipe/qt/core" ++ "github.com/therecipe/qt/gui" ++ "github.com/therecipe/qt/uitools" ++ "github.com/therecipe/qt/widgets" ++) ++ ++// MainUI defines the data for the main ui (that one with the chats) ++type MainUI struct { ++ widget *widgets.QWidget ++ cli *gomatrix.Client ++ window *widgets.QMainWindow ++ windowWidth int ++ windowHeight int ++} ++ ++// NewMainUI gives you a MainUI struct with prefilled data ++func NewMainUI(windowWidth, windowHeight int, window *widgets.QMainWindow) (mainUI *MainUI) { ++ mainUI = &MainUI{ ++ windowWidth: windowWidth, ++ windowHeight: windowHeight, ++ window: window, ++ } ++ return ++} ++ ++// SetCli sets the gomatrix Client for the MainUI ++func (m *MainUI) SetCli(cli *gomatrix.Client) { ++ m.cli = cli ++} ++ ++// GetWidget returns the QWidget of the MainUI ++func (m *MainUI) GetWidget() (widget *widgets.QWidget) { ++ return m.widget ++} ++ ++// NewUI prepares the new UI ++func (m *MainUI) NewUI() error { ++ m.widget = widgets.NewQWidget(nil, 0) ++ ++ var loader = uitools.NewQUiLoader(nil) ++ var file = core.NewQFile2(":/qml/ui/chat.ui") ++ ++ file.Open(core.QIODevice__ReadOnly) ++ mainWidget := loader.Load(file, m.widget) ++ file.Close() ++ ++ var layout = widgets.NewQHBoxLayout() ++ m.window.SetLayout(layout) ++ layout.InsertWidget(0, mainWidget, 0, core.Qt__AlignTop|core.Qt__AlignLeft) ++ layout.SetSpacing(0) ++ layout.SetContentsMargins(0, 0, 0, 0) ++ ++ m.widget.ConnectResizeEvent(func(event *gui.QResizeEvent) { ++ mainWidget.Resize(event.Size()) ++ event.Accept() ++ }) ++ ++ return nil ++} +diff --git a/pkg/matrix/dataTypes.go b/pkg/matrix/dataTypes.go +new file mode 100644 +index 0000000..8d30e68 +--- /dev/null ++++ b/pkg/matrix/dataTypes.go +@@ -0,0 +1,38 @@ ++package matrix ++ ++import ( ++ "github.com/matrix-org/gomatrix" ++ "time" ++) ++ ++// User defines a Interface to allow multiple User type Implementations ++type User interface { ++ SetCli(cli *gomatrix.Client) ++ SetMXID(id string) ++ GetDisplayName(roomID string) (string, error) ++ GetAvatar(roomID string) (string, error) ++} ++ ++// Room defines a Interface to allow multiple Room type Implementations ++type Room interface { ++ // Handled using global "own User" ++ //SetCli(cli *gomatrix.Client) ++ SetRoomID(id string) ++ SetRoomAliases(aliases map[int64]string) ++ GetName() (string, error) ++ GetAvatar() (string, error) ++ GetTopic() (string, error) ++ GetMessages() (map[string]Message, error) ++} ++ ++// Message defines a Interface to allow multiple Message type Implementations ++type Message interface { ++ // Handled using global "own User" ++ //SetCli(cli *gomatrix.Client) ++ SetEventID(id string) ++ SetEvent(event *gomatrix.Event) ++ SetAuthorMXID(mxid string) ++ SetMessage(message string) ++ SetTimestamp(ts *time.Time) ++ Show() error ++} diff --git a/pulls/4.json b/pulls/4.json @@ -0,0 +1,22 @@ +{ + "number": 4, + "title": "Implement basic state managment for rooms, messages, users (not state as in matrix proto state)", + "state": "merged", + "diff_file": "4.diff", + "author": "MTRNord", + "created_at": "2018-05-02T16:43:24Z", + "closed_at": "2018-05-02T17:47:47Z", + "merged_at": "2018-05-02T17:47:47Z", + "base_ref": "master", + "head_ref": "develop", + "labels": [ + "enhancement" + ], + "assignees": [ + "MTRNord" + ], + "requested_reviewers": [], + "body": "", + "comments": [], + "review_comments": [] +} diff --git a/pulls/4.md b/pulls/4.md @@ -0,0 +1,15 @@ +# PR #4 Implement basic state managment for rooms, messages, users (not state as in matrix proto state) + +- **Status:** merged +- **Author:** @MTRNord +- **Created:** 2018-05-02T16:43:24Z +- **Branch:** develop → master +- **Merged:** 2018-05-02T17:47:47Z +- **Labels:** enhancement +- **Assignees:** @MTRNord +- **Diff:** [4.diff](./4.diff) + +--- + +_No description._ + diff --git a/pulls/6.diff b/pulls/6.diff @@ -0,0 +1,1269 @@ +diff --git a/Gopkg.lock b/Gopkg.lock +index 7859130..629ec69 100644 +--- a/Gopkg.lock ++++ b/Gopkg.lock +@@ -13,6 +13,12 @@ + packages = ["."] + revision = "a7fc80c8060c2544fe5d4dae465b584f8e9b4e27" + ++[[projects]] ++ name = "github.com/mattn/go-sqlite3" ++ packages = ["."] ++ revision = "6c771bb9887719704b210e87e934f08be014bdb1" ++ version = "v1.6.0" ++ + [[projects]] + branch = "master" + name = "github.com/shibukawa/configdir" +@@ -34,6 +40,6 @@ + [solve-meta] + analyzer-name = "dep" + analyzer-version = 1 +- inputs-digest = "c22db96d1e74b32e9427a6f762b2be5797dcc8426407dc4769795fe6ca7296be" ++ inputs-digest = "f746b36e895639f6b0cbe2cb4d928637d254f83f60346a95eaf5c0f383683229" + solver-name = "gps-cdcl" + solver-version = 1 +diff --git a/cmd/root.go b/cmd/root.go +index 148f65a..9b10937 100644 +--- a/cmd/root.go ++++ b/cmd/root.go +@@ -19,7 +19,8 @@ import ( + "os" + + "github.com/Nordgedanken/Morpheusv2/pkg/app" +- dbImpl "github.com/Nordgedanken/Morpheusv2/pkg/db/implementation" ++ "github.com/Nordgedanken/Morpheusv2/pkg/db/sqlite" ++ "github.com/Nordgedanken/Morpheusv2/pkg/util" + "github.com/shibukawa/configdir" + "github.com/spf13/cobra" + "io" +@@ -47,7 +48,7 @@ var rootCmd = &cobra.Command{ + } + + // os.OpenFile opens the file where the log is supposed to be written to +- logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) ++ logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0600) + if err != nil { + return err + } +@@ -59,7 +60,8 @@ var rootCmd = &cobra.Command{ + log.SetOutput(mw) + + // dbImpl.Init() generates the needed tables if needed before the app starts +- err = dbImpl.Init() ++ util.DB = &sqlite.SQLite{} ++ err = util.DB.Init() + if err != nil { + return err + } +diff --git a/pkg/app/main.go b/pkg/app/main.go +index 3832900..255f074 100644 +--- a/pkg/app/main.go ++++ b/pkg/app/main.go +@@ -15,7 +15,10 @@ + package app + + import ( ++ "database/sql" ++ "github.com/Nordgedanken/Morpheusv2/pkg/loginUI" + "github.com/Nordgedanken/Morpheusv2/pkg/mainUI" ++ "github.com/Nordgedanken/Morpheusv2/pkg/util" + "github.com/matrix-org/gomatrix" + "github.com/therecipe/qt/core" + "github.com/therecipe/qt/gui" +@@ -36,11 +39,20 @@ func Start(argsArg []string) error { + + initApp() + +- mainUIS := mainUI.NewMainUI(windowWidth, windowHeight, window) +- SetNewWindow(mainUIS, window) ++ _, err := util.DB.GetCurrentUser() ++ // We special case ErrNoRows because this is expected to happen if user is missing ++ if err == sql.ErrNoRows { ++ loginUIs := loginUI.NewLoginUI(windowWidth, windowHeight, window) ++ SetNewWindow(loginUIs, window) ++ } else if err != nil { ++ return err ++ } else { ++ mainUIs := mainUI.NewMainUI(windowWidth, windowHeight, window) ++ SetNewWindow(mainUIs, window) ++ } + + widgets.QApplication_Exec() +- ++ + return nil + } + +@@ -65,7 +77,7 @@ func initApp() { + window.Resize2(windowWidth, windowHeight) + window.Move2(windowX, windowY) + +- app.ConnectQuit(func() { ++ window.ConnectCloseEvent(func(event *gui.QCloseEvent) { + log.Println("Morpheus closed") + }) + +diff --git a/pkg/app/ui.go b/pkg/app/ui.go +index 37ced17..7273079 100644 +--- a/pkg/app/ui.go ++++ b/pkg/app/ui.go +@@ -1,3 +1,17 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ + package app + + import ( +diff --git a/pkg/db/db.go b/pkg/db/db.go +index 0ffaede..27f04b8 100644 +--- a/pkg/db/db.go ++++ b/pkg/db/db.go +@@ -1,14 +1,37 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ + package db + +-import "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++import ( ++ "database/sql" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++) + + // DB defines a Interface to allow multiple DB Implementations + type DB interface { ++ Init() error ++ Open() *sql.DB ++ + SaveRoom(Room matrix.Room) error +- GetRooms() (rooms map[string]matrix.Room, err error) +- GetRoom(roomID string) (room matrix.Room, err error) ++ GetRooms() (roomsR []matrix.Room, err error) ++ GetRoom(roomID string) (roomR matrix.Room, err error) + + SaveUser(user matrix.User) error +- GetUsers() (map[string]matrix.User, error) +- GetCurrentUser() (matrix.User, error) ++ GetUser(userID string) (userR matrix.User, err error) ++ GetCurrentUser() (userR matrix.User, err error) ++ ++ SaveMessage(message matrix.Message) error ++ GetMessage(eventID string) (messageR matrix.Message, err error) + } +diff --git a/pkg/db/sqlite/db.go b/pkg/db/sqlite/db.go +new file mode 100644 +index 0000000..fa80421 +--- /dev/null ++++ b/pkg/db/sqlite/db.go +@@ -0,0 +1,62 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package sqlite ++ ++import ( ++ "database/sql" ++ "fmt" ++ _ "github.com/mattn/go-sqlite3" // Go-sqlite3 side effect import needed to use SQLite3 databases ++ "github.com/shibukawa/configdir" ++ "log" ++ "path/filepath" ++) ++ ++// Init prepares the DB by opening it and creating the required tables if needed ++func (s *SQLite) Init() (err error) { ++ log.Println("Start setting up DB") ++ var openErr error ++ ++ // Open the data.db file. It will be created if it doesn't exist. ++ configDirs := configdir.New("Nordgedanken", "Morpheusv2") ++ filePath := filepath.ToSlash(configDirs.QueryFolders(configdir.Global)[0].Path) ++ ++ log.Println("DBFilePath: ", filePath+"/data.db") ++ s.db, openErr = sql.Open("sqlite3", filePath+"/data.db") ++ if openErr != nil { ++ err = openErr ++ return ++ } ++ ++ log.Println("Creating DB Tables if needed") ++ createTables := `CREATE TABLE IF NOT EXISTS users (id varchar not null primary key, display_name text, avatar text, access_token text, own integer); ++ CREATE TABLE IF NOT EXISTS messages (id varchar not null primary key, author_id varchar, message text, timestamp datetime, pure_event text); ++ 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); ++ ` ++ _, execErr := s.db.Exec(createTables) ++ if execErr != nil { ++ err = fmt.Errorf("DB EXEC ERR: %s", execErr) ++ return ++ } ++ log.Println("Finished setting DB Setup") ++ return ++} ++ ++// Open returns the in Init() created db variable ++func (s *SQLite) Open() *sql.DB { ++ if s.db != nil { ++ return s.db ++ } ++ return nil ++} +diff --git a/pkg/db/sqlite/messages.go b/pkg/db/sqlite/messages.go +new file mode 100644 +index 0000000..6b709d7 +--- /dev/null ++++ b/pkg/db/sqlite/messages.go +@@ -0,0 +1,93 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package sqlite ++ ++import ( ++ "encoding/json" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix/messages" ++ "github.com/matrix-org/gomatrix" ++ "time" ++) ++ ++// SaveMessage saves message Events to the DB ++func (s *SQLite) SaveMessage(message matrix.Message) error { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ tx, err := s.db.Begin() ++ if err != nil { ++ return err ++ } ++ ++ stmt, err := tx.Prepare("INSERT INTO messages (id, author_id, message, timestamp, pure_event) VALUES (?, ?, ?, ?, ?)") ++ if err != nil { ++ return err ++ } ++ defer stmt.Close() ++ ++ id := message.GetEventID() ++ authorID := message.GetAuthorMXID() ++ messageS := message.GetMessage() ++ timestampR := message.GetTimestamp() ++ timestamp := timestampR.Format("2006-01-02 15:04:05") ++ pureEvent := message.GetEvent() ++ _, err = stmt.Exec(id, authorID, messageS, timestamp, pureEvent) ++ if err != nil { ++ return err ++ } ++ ++ return tx.Commit() ++} ++ ++// GetMessage returns the Message where the id matches the eventID ++func (s *SQLite) GetMessage(eventID string) (messageR matrix.Message, err error) { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ stmt, err := s.db.Prepare(`SELECT author_id, message, timestamp, pure_event FROM messages WHERE id=$1`) ++ if err != nil { ++ return ++ } ++ defer stmt.Close() ++ ++ row := stmt.QueryRow(eventID) ++ ++ var authorID string ++ var messageS string ++ var timestamp time.Time ++ var pureEvent string ++ err = row.Scan(&authorID, &messageS, &timestamp, &pureEvent) ++ if err != nil { ++ return ++ } ++ ++ messageI := &messages.Message{} ++ messageI.SetEventID(eventID) ++ messageI.SetAuthorMXID(authorID) ++ messageI.SetMessage(messageS) ++ messageI.SetTimestamp(&timestamp) ++ var gomatrixEvent gomatrix.Event ++ err = json.Unmarshal([]byte(pureEvent), &gomatrixEvent) ++ if err != nil { ++ return ++ } ++ messageI.SetEvent(&gomatrixEvent) ++ ++ messageR = messageI ++ return ++} +diff --git a/pkg/db/sqlite/rooms.go b/pkg/db/sqlite/rooms.go +new file mode 100644 +index 0000000..1bfd627 +--- /dev/null ++++ b/pkg/db/sqlite/rooms.go +@@ -0,0 +1,172 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package sqlite ++ ++import ( ++ "encoding/json" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix/rooms" ++) ++ ++// SaveRoom saves a Room into the sqlite DB ++func (s *SQLite) SaveRoom(Room matrix.Room) error { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ tx, err := s.db.Begin() ++ if err != nil { ++ return err ++ } ++ ++ stmt, err := tx.Prepare("INSERT INTO rooms (room_aliases, id, room_name, room_avatar, room_topic, room_messages) VALUES (?, ?, ?, ?, ?, ?)") ++ if err != nil { ++ return err ++ } ++ defer stmt.Close() ++ ++ aliases := Room.GetRoomAliases() ++ aliasesBytes, err := json.Marshal(aliases) ++ if err != nil { ++ return err ++ } ++ aliasesS := string(aliasesBytes) ++ roomID := Room.GetRoomID() ++ name, err := Room.GetName() ++ if err != nil { ++ return err ++ } ++ avatar, err := Room.GetAvatar() ++ if err != nil { ++ return err ++ } ++ topic, err := Room.GetTopic() ++ if err != nil { ++ return err ++ } ++ ++ messages := Room.GetMessages() ++ if err != nil { ++ return err ++ } ++ var messageIDs []string ++ for _, v := range messages { ++ messageIDs = append(messageIDs, v.GetEventID()) ++ } ++ ++ _, err = stmt.Exec(aliasesS, roomID, name, string(avatar), topic, messageIDs) ++ if err != nil { ++ return err ++ } ++ return tx.Commit() ++} ++ ++// GetRooms returns all Rooms from the Database ++func (s *SQLite) GetRooms() (roomsR []matrix.Room, err error) { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ rows, err := s.db.Query("SELECT id, room_aliases, room_name, room_avatar, room_topic, room_messages FROM rooms") ++ if err != nil { ++ return ++ } ++ defer rows.Close() ++ ++ for rows.Next() { ++ var roomID string ++ var roomAliases string ++ var roomName string ++ var roomAvatar string ++ var roomTopic string ++ var roomMessages string ++ err = rows.Scan(&roomID, &roomAliases, &roomName, &roomAvatar, &roomTopic, &roomMessages) ++ if err != nil { ++ return ++ } ++ ++ roomI := &rooms.Room{} ++ roomI.SetRoomID(roomID) ++ var aliases []string ++ err = json.Unmarshal([]byte(roomAliases), &aliases) ++ if err != nil { ++ return ++ } ++ roomI.SetRoomAliases(aliases) ++ roomI.SetName(roomName) ++ roomI.SetAvatar([]byte(roomAvatar)) ++ roomI.SetTopic(roomTopic) ++ var messageIDs []string ++ err = json.Unmarshal([]byte(roomMessages), &messageIDs) ++ if err != nil { ++ return ++ } ++ // TODO Convert IDs to messages slice using another call or from the beginning on using a JOIN ++ //roomI.SetMessages(messages) ++ ++ roomsR = append(roomsR, roomI) ++ } ++ ++ // get any error encountered during iteration ++ err = rows.Err() ++ return ++} ++ ++// GetRoom returns the Room where the id matches the roomID ++func (s *SQLite) GetRoom(roomID string) (roomR matrix.Room, err error) { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ stmt, err := s.db.Prepare(`SELECT room_aliases, room_name, room_avatar, room_topic, room_messages FROM rooms WHERE id=$1`) ++ if err != nil { ++ return ++ } ++ defer stmt.Close() ++ ++ row := stmt.QueryRow(roomID) ++ ++ var roomAliases string ++ var roomName string ++ var roomAvatar string ++ var roomTopic string ++ var roomMessages string ++ err = row.Scan(&roomAliases, &roomName, &roomAvatar, &roomTopic, &roomMessages) ++ if err != nil { ++ return ++ } ++ ++ roomI := &rooms.Room{} ++ roomI.SetRoomID(roomID) ++ var aliases []string ++ err = json.Unmarshal([]byte(roomAliases), &aliases) ++ if err != nil { ++ return ++ } ++ roomI.SetRoomAliases(aliases) ++ roomI.SetName(roomName) ++ roomI.SetAvatar([]byte(roomAvatar)) ++ roomI.SetTopic(roomTopic) ++ var messageIDs []string ++ err = json.Unmarshal([]byte(roomMessages), &messageIDs) ++ if err != nil { ++ return ++ } ++ // TODO Convert IDs to messages slice using another call or from the beginning on using a JOIN ++ //roomI.SetMessages(messages) ++ ++ roomR = roomI ++ return ++} +diff --git a/pkg/db/sqlite/struct.go b/pkg/db/sqlite/struct.go +new file mode 100644 +index 0000000..6497773 +--- /dev/null ++++ b/pkg/db/sqlite/struct.go +@@ -0,0 +1,22 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package sqlite ++ ++import "database/sql" ++ ++// SQLite implements a SQLite database for the db.DB interface ++type SQLite struct { ++ db *sql.DB ++} +diff --git a/pkg/db/sqlite/users.go b/pkg/db/sqlite/users.go +new file mode 100644 +index 0000000..e78a6a6 +--- /dev/null ++++ b/pkg/db/sqlite/users.go +@@ -0,0 +1,125 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package sqlite ++ ++import ( ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix/users" ++ "github.com/matrix-org/gomatrix" ++ "strings" ++) ++ ++// SaveUser saves a matrix User to the User table ++func (s *SQLite) SaveUser(user matrix.User) error { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ tx, err := s.db.Begin() ++ if err != nil { ++ return err ++ } ++ ++ stmt, err := tx.Prepare("INSERT INTO users (id, display_name, avatar) VALUES (?, ?, ?)") ++ if err != nil { ++ return err ++ } ++ defer stmt.Close() ++ displayName, err := user.GetDisplayName("") ++ if err != nil { ++ return err ++ } ++ avatar, err := user.GetAvatar("") ++ if err != nil { ++ return err ++ } ++ mxid := user.GetMXID() ++ _, err = stmt.Exec(mxid, displayName, string(avatar)) ++ if err != nil { ++ return err ++ } ++ ++ return tx.Commit() ++} ++ ++// GetCurrentUser returns the current user including a ready gomatrix client ++func (s *SQLite) GetCurrentUser() (userR matrix.User, err error) { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ stmt, err := s.db.Prepare(`SELECT id, display_name, avatar, access_token FROM users WHERE own=1`) ++ if err != nil { ++ return ++ } ++ defer stmt.Close() ++ ++ row := stmt.QueryRow() ++ ++ var mxid string ++ var displayName string ++ var avatar string ++ var accessToken string ++ err = row.Scan(&mxid, &displayName, &avatar, &accessToken) ++ if err != nil { ++ return ++ } ++ ++ userI := &users.User{} ++ userI.SetMXID(mxid) ++ userI.SetDisplayName("", displayName) ++ userI.SetAvatar("", []byte(avatar)) ++ ++ splitUser := strings.Split(mxid, ":") ++ domain := strings.TrimPrefix(mxid, splitUser[0]+":") ++ client, err := gomatrix.NewClient(domain, mxid, accessToken) ++ if err != nil { ++ return ++ } ++ userI.SetCli(client) ++ ++ userR = userI ++ return ++} ++ ++// GetUser returns a user matching the mxid of the argument ++func (s *SQLite) GetUser(userID string) (userR matrix.User, err error) { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ stmt, err := s.db.Prepare(`SELECT display_name, avatar FROM users WHERE id=$1`) ++ if err != nil { ++ return ++ } ++ defer stmt.Close() ++ ++ row := stmt.QueryRow(userID) ++ ++ var displayName string ++ var avatar string ++ err = row.Scan(&displayName, &avatar) ++ if err != nil { ++ return ++ } ++ ++ userI := &users.User{} ++ userI.SetMXID(userID) ++ userI.SetDisplayName("", displayName) ++ userI.SetAvatar("", []byte(avatar)) ++ ++ userR = userI ++ return ++} +diff --git a/pkg/loginUI/loginUI.go b/pkg/loginUI/loginUI.go +new file mode 100644 +index 0000000..fa3d993 +--- /dev/null ++++ b/pkg/loginUI/loginUI.go +@@ -0,0 +1,77 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package loginUI ++ ++import ( ++ "github.com/matrix-org/gomatrix" ++ "github.com/therecipe/qt/core" ++ "github.com/therecipe/qt/gui" ++ "github.com/therecipe/qt/uitools" ++ "github.com/therecipe/qt/widgets" ++) ++ ++// LoginUI defines the data for the login ui ++type LoginUI struct { ++ widget *widgets.QWidget ++ cli *gomatrix.Client ++ window *widgets.QMainWindow ++ windowWidth int ++ windowHeight int ++} ++ ++// NewLoginUI gives you a MainUI struct with profiled data ++func NewLoginUI(windowWidth, windowHeight int, window *widgets.QMainWindow) (loginUI *LoginUI) { ++ loginUI = &LoginUI{ ++ windowWidth: windowWidth, ++ windowHeight: windowHeight, ++ window: window, ++ } ++ return ++} ++ ++// SetCli sets the gomatrix Client for the LoginUI ++func (m *LoginUI) SetCli(cli *gomatrix.Client) { ++ m.cli = cli ++} ++ ++// GetWidget returns the QWidget of the LoginUI ++func (m *LoginUI) GetWidget() (widget *widgets.QWidget) { ++ return m.widget ++} ++ ++// NewUI prepares the new UI ++func (m *LoginUI) NewUI() error { ++ m.widget = widgets.NewQWidget(nil, 0) ++ ++ var loader = uitools.NewQUiLoader(nil) ++ var file = core.NewQFile2(":/qml/ui/login.ui") ++ ++ file.Open(core.QIODevice__ReadOnly) ++ mainWidget := loader.Load(file, m.widget) ++ file.Close() ++ ++ var layout = widgets.NewQHBoxLayout() ++ m.window.SetLayout(layout) ++ layout.InsertWidget(0, mainWidget, 0, core.Qt__AlignTop|core.Qt__AlignLeft) ++ layout.SetSpacing(0) ++ layout.SetContentsMargins(0, 0, 0, 0) ++ ++ m.widget.ConnectResizeEvent(func(event *gui.QResizeEvent) { ++ mainWidget.Resize(event.Size()) ++ event.Accept() ++ }) ++ ++ return nil ++} +diff --git a/pkg/mainUI/mainUI.go b/pkg/mainUI/mainUI.go +index 7fcaaf9..a8cddc3 100644 +--- a/pkg/mainUI/mainUI.go ++++ b/pkg/mainUI/mainUI.go +@@ -1,3 +1,17 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ + package mainUI + + import ( +diff --git a/pkg/matrix/dataTypes.go b/pkg/matrix/dataTypes.go +index 8d30e68..a010373 100644 +--- a/pkg/matrix/dataTypes.go ++++ b/pkg/matrix/dataTypes.go +@@ -1,3 +1,17 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ + package matrix + + import ( +@@ -9,8 +23,15 @@ import ( + type User interface { + SetCli(cli *gomatrix.Client) + SetMXID(id string) ++ SetDisplayName(roomID string, name string) ++ SetAvatar(roomID string, avatar []byte) ++ ++ GetMXID() string + GetDisplayName(roomID string) (string, error) +- GetAvatar(roomID string) (string, error) ++ GetAvatar(roomID string) ([]byte, error) ++ GetCli() (cli *gomatrix.Client) ++ ++ //Implement MarshalJSON() (b []byte, e error) as in http://gregtrowbridge.com/golang-json-serialization-with-interfaces/ to support json + } + + // Room defines a Interface to allow multiple Room type Implementations +@@ -18,11 +39,20 @@ type Room interface { + // Handled using global "own User" + //SetCli(cli *gomatrix.Client) + SetRoomID(id string) +- SetRoomAliases(aliases map[int64]string) ++ SetRoomAliases(aliases []string) ++ SetName(name string) ++ SetAvatar(avatar []byte) ++ SetTopic(topic string) ++ SetMessages(messages []Message) ++ ++ GetRoomID() string ++ GetRoomAliases() []string + GetName() (string, error) +- GetAvatar() (string, error) ++ GetAvatar() ([]byte, error) + GetTopic() (string, error) +- GetMessages() (map[string]Message, error) ++ GetMessages() []Message ++ ++ //Implement MarshalJSON() (b []byte, e error) as in http://gregtrowbridge.com/golang-json-serialization-with-interfaces/ to support json + } + + // Message defines a Interface to allow multiple Message type Implementations +@@ -34,5 +64,14 @@ type Message interface { + SetAuthorMXID(mxid string) + SetMessage(message string) + SetTimestamp(ts *time.Time) ++ ++ GetEventID() (id string) ++ GetEvent() (event *gomatrix.Event) ++ GetAuthorMXID() (mxid string) ++ GetMessage() (message string) ++ GetTimestamp() (ts *time.Time) ++ + Show() error ++ ++ //Implement MarshalJSON() (b []byte, e error) as in http://gregtrowbridge.com/golang-json-serialization-with-interfaces/ to support json + } +diff --git a/pkg/matrix/messages/message.go b/pkg/matrix/messages/message.go +new file mode 100644 +index 0000000..186fdda +--- /dev/null ++++ b/pkg/matrix/messages/message.go +@@ -0,0 +1,85 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package messages ++ ++import ( ++ "github.com/matrix-org/gomatrix" ++ "time" ++) ++ ++// Message holds the needed Message data and allows to work with that. It gets normally loaded from the cache ++type Message struct { ++ eventID string ++ event *gomatrix.Event ++ authorID string ++ text string ++ timestamp *time.Time ++} ++ ++// SetEventID adds the eventID to the current Message ++func (m *Message) SetEventID(id string) { ++ m.eventID = id ++} ++ ++// SetEvent adds the gomatrix Event to the current Message ++func (m *Message) SetEvent(event *gomatrix.Event) { ++ m.event = event ++} ++ ++// SetAuthorMXID adds the author MXID to the current Message ++func (m *Message) SetAuthorMXID(mxid string) { ++ m.authorID = mxid ++} ++ ++// SetMessage adds the message Text to the current Message ++func (m *Message) SetMessage(message string) { ++ m.text = message ++} ++ ++// SetTimestamp adds the Timestamp to the current Message ++func (m *Message) SetTimestamp(ts *time.Time) { ++ m.timestamp = ts ++} ++ ++// GetEventID returns the event ID from the current Message ++func (m *Message) GetEventID() (id string) { ++ return m.eventID ++} ++ ++// GetEvent returns the gomatrix event from the current Message ++func (m *Message) GetEvent() (event *gomatrix.Event) { ++ return m.event ++} ++ ++// GetAuthorMXID returns the authors mxid from the current Message ++func (m *Message) GetAuthorMXID() (mxid string) { ++ return m.authorID ++} ++ ++// GetMessage returns the text from the current Message ++func (m *Message) GetMessage() (message string) { ++ return m.text ++} ++ ++// GetTimestamp returns the timestamp from the current Message ++func (m *Message) GetTimestamp() (ts *time.Time) { ++ return m.timestamp ++} ++ ++// Show adds the current Message to the UI ++// TODO implement it ++func (m *Message) Show() error { ++ return nil ++} +diff --git a/pkg/matrix/rooms/room.go b/pkg/matrix/rooms/room.go +new file mode 100644 +index 0000000..9d884ce +--- /dev/null ++++ b/pkg/matrix/rooms/room.go +@@ -0,0 +1,145 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package rooms ++ ++import ( ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++ "github.com/Nordgedanken/Morpheusv2/pkg/util" ++ "github.com/matrix-org/gomatrix" ++ "strings" ++) ++ ++// Room holds the needed Room data and allows to work with that. It gets normally loaded from the cache ++type Room struct { ++ id string ++ aliases []string ++ name string ++ avatar []byte ++ topic string ++ messages []matrix.Message ++} ++ ++// SetRoomID adds the roomID to the current Room ++func (r *Room) SetRoomID(id string) { ++ r.id = id ++} ++ ++// SetRoomAliases adds the aliases to the current Room ++func (r *Room) SetRoomAliases(aliases []string) { ++ r.aliases = aliases ++} ++ ++// SetName adds the name to the current Room ++func (r *Room) SetName(name string) { ++ r.name = name ++} ++ ++// SetAvatar adds the avatar to the current Room ++func (r *Room) SetAvatar(avatar []byte) { ++ r.avatar = avatar ++} ++ ++// SetTopic adds the topic to the current Room ++func (r *Room) SetTopic(topic string) { ++ r.topic = topic ++} ++ ++// SetMessages adds the messages to the current Room ++func (r *Room) SetMessages(messages []matrix.Message) { ++ r.messages = messages ++} ++ ++// GetRoomID returns the room ID from the current Room ++func (r *Room) GetRoomID() string { ++ return r.id ++} ++ ++// GetRoomAliases returns the room aliases from the current Room ++func (r *Room) GetRoomAliases() []string { ++ return r.aliases ++} ++ ++// GetName returns the name from the current Room ++func (r *Room) GetName() (string, error) { ++ if r.name == "" { ++ type RespRoomName struct { ++ Name string `json:"name"` ++ } ++ resp := &RespRoomName{} ++ err := util.User.GetCli().StateEvent(r.id, "m.room.name", "", resp) ++ if err != nil { ++ return "", err ++ } ++ r.name = resp.Name ++ } ++ return r.name, nil ++} ++ ++// GetAvatar returns the avatar from the current Room ++func (r *Room) GetAvatar() ([]byte, error) { ++ if r.avatar == nil { ++ resp := &gomatrix.Event{} ++ err := util.User.GetCli().StateEvent(r.id, "m.room.avatar", "", resp) ++ if err != nil { ++ return nil, err ++ } ++ var avatar []byte ++ value, exists := resp.Content["url"] ++ if !exists { ++ return nil, nil ++ } ++ url, ok := value.(string) ++ if !ok { ++ return nil, nil ++ } ++ split := strings.Split(url, "/") ++ servername := strings.TrimPrefix(split[0], "mxc://") ++ mediaID := split[1] ++ mediaURL := util.User.GetCli().BuildBaseURL("_matrix/media/r0/download", servername, mediaID) ++ avatar, err = util.User.GetCli().MakeRequest("GET", mediaURL, nil, nil) ++ if err != nil { ++ return nil, err ++ } ++ r.avatar = avatar ++ } ++ return r.avatar, nil ++} ++ ++// GetTopic returns the topic from the current Room ++func (r *Room) GetTopic() (string, error) { ++ if r.topic == "" { ++ resp := &gomatrix.Event{} ++ err := util.User.GetCli().StateEvent(r.id, "m.room.topic", "", resp) ++ if err != nil { ++ return "", err ++ } ++ value, exists := resp.Content["topic"] ++ if !exists { ++ return "", nil ++ } ++ topic, ok := value.(string) ++ if !ok { ++ return "", nil ++ } ++ r.topic = topic ++ } ++ return r.topic, nil ++} ++ ++// GetMessages returns the messages from the current Room ++func (r *Room) GetMessages() []matrix.Message { ++ // TODO Lazy load from DB ++ return r.messages ++} +diff --git a/pkg/matrix/users/user.go b/pkg/matrix/users/user.go +new file mode 100644 +index 0000000..8cee5cf +--- /dev/null ++++ b/pkg/matrix/users/user.go +@@ -0,0 +1,127 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package users ++ ++import ( ++ "github.com/Nordgedanken/Morpheusv2/pkg/util" ++ "github.com/matrix-org/gomatrix" ++ "strings" ++) ++ ++// User holds the needed User data and allows to work with that. It gets normally loaded from the cache ++type User struct { ++ cli *gomatrix.Client ++ mxid string ++ defaultDisplayName string ++ displayName map[string]string ++ defaultAvatar []byte ++ avatar map[string][]byte ++} ++ ++// 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. ++func (u *User) SetCli(cli *gomatrix.Client) { ++ u.cli = cli ++} ++ ++// SetMXID adds the mxid to the current User ++func (u *User) SetMXID(id string) { ++ u.mxid = id ++} ++ ++// SetDisplayName adds the displayName to the current User ++func (u *User) SetDisplayName(roomID string, name string) { ++ if roomID == "" { ++ u.defaultDisplayName = name ++ } else { ++ if u.displayName == nil { ++ u.displayName = make(map[string]string) ++ } ++ u.displayName[roomID] = name ++ } ++} ++ ++// SetAvatar adds the avatar to the current User ++func (u *User) SetAvatar(roomID string, avatar []byte) { ++ if roomID == "" { ++ u.defaultAvatar = avatar ++ } else { ++ if u.avatar == nil { ++ u.avatar = make(map[string][]byte) ++ } ++ u.avatar[roomID] = avatar ++ } ++} ++ ++// GetMXID returns the mxid from the current User ++func (u *User) GetMXID() string { ++ return u.mxid ++} ++ ++// GetDisplayName returns the displayName from the current User ++func (u *User) GetDisplayName(roomID string) (string, error) { ++ if roomID == "" { ++ if u.defaultDisplayName == "" { ++ resp, err := util.User.GetCli().GetDisplayName(u.mxid) ++ if err != nil { ++ return "", err ++ } ++ u.defaultDisplayName = resp.DisplayName ++ } ++ return u.defaultDisplayName, nil ++ } ++ // TODO get Membership Event from Room instead returning default directly ++ if u.displayName[roomID] == "" { ++ return u.defaultDisplayName, nil ++ } ++ return u.displayName[roomID], nil ++} ++ ++// GetAvatar returns the avatar from the current User ++func (u *User) GetAvatar(roomID string) ([]byte, error) { ++ if roomID == "" { ++ if u.defaultAvatar == nil { ++ urlPath := util.User.GetCli().BuildURL("profile", u.mxid, "avatar_url") ++ s := struct { ++ AvatarURL string `json:"avatar_url"` ++ }{} ++ ++ _, err := util.User.GetCli().MakeRequest("GET", urlPath, nil, &s) ++ if err != nil { ++ return nil, err ++ } ++ ++ split := strings.Split(s.AvatarURL, "/") ++ servername := strings.TrimPrefix(split[0], "mxc://") ++ mediaID := split[1] ++ mediaURL := util.User.GetCli().BuildBaseURL("_matrix/media/r0/download", servername, mediaID) ++ avatar, err := util.User.GetCli().MakeRequest("GET", mediaURL, nil, nil) ++ if err != nil { ++ return nil, err ++ } ++ u.defaultAvatar = avatar ++ } ++ return u.defaultAvatar, nil ++ } ++ // TODO get Membership Event from Room instead returning default directly ++ if u.avatar[roomID] == nil { ++ return u.defaultAvatar, nil ++ } ++ return u.avatar[roomID], nil ++} ++ ++// GetCli returns the gomatrix.Client from the current User ++func (u *User) GetCli() *gomatrix.Client { ++ return u.cli ++} +diff --git a/pkg/util/vars.go b/pkg/util/vars.go +new file mode 100644 +index 0000000..7325755 +--- /dev/null ++++ b/pkg/util/vars.go +@@ -0,0 +1,26 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package util ++ ++import ( ++ "github.com/Nordgedanken/Morpheusv2/pkg/db" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++) ++ ++// DB holds the main pointer to the Database ++var DB db.DB ++ ++// User holds the Current User ++var User matrix.User diff --git a/pulls/6.json b/pulls/6.json @@ -0,0 +1,22 @@ +{ + "number": 6, + "title": "Finish backend work", + "state": "merged", + "diff_file": "6.diff", + "author": "MTRNord", + "created_at": "2018-05-05T23:01:20Z", + "closed_at": "2018-05-05T23:09:51Z", + "merged_at": "2018-05-05T23:09:51Z", + "base_ref": "master", + "head_ref": "develop", + "labels": [ + "enhancement" + ], + "assignees": [ + "MTRNord" + ], + "requested_reviewers": [], + "body": "Still todo is interface to json processing", + "comments": [], + "review_comments": [] +} diff --git a/pulls/6.md b/pulls/6.md @@ -0,0 +1,15 @@ +# PR #6 Finish backend work + +- **Status:** merged +- **Author:** @MTRNord +- **Created:** 2018-05-05T23:01:20Z +- **Branch:** develop → master +- **Merged:** 2018-05-05T23:09:51Z +- **Labels:** enhancement +- **Assignees:** @MTRNord +- **Diff:** [6.diff](./6.diff) + +--- + +Still todo is interface to json processing + diff --git a/pulls/7.diff b/pulls/7.diff @@ -0,0 +1,1269 @@ +diff --git a/Gopkg.lock b/Gopkg.lock +index 7859130..629ec69 100644 +--- a/Gopkg.lock ++++ b/Gopkg.lock +@@ -13,6 +13,12 @@ + packages = ["."] + revision = "a7fc80c8060c2544fe5d4dae465b584f8e9b4e27" + ++[[projects]] ++ name = "github.com/mattn/go-sqlite3" ++ packages = ["."] ++ revision = "6c771bb9887719704b210e87e934f08be014bdb1" ++ version = "v1.6.0" ++ + [[projects]] + branch = "master" + name = "github.com/shibukawa/configdir" +@@ -34,6 +40,6 @@ + [solve-meta] + analyzer-name = "dep" + analyzer-version = 1 +- inputs-digest = "c22db96d1e74b32e9427a6f762b2be5797dcc8426407dc4769795fe6ca7296be" ++ inputs-digest = "f746b36e895639f6b0cbe2cb4d928637d254f83f60346a95eaf5c0f383683229" + solver-name = "gps-cdcl" + solver-version = 1 +diff --git a/cmd/root.go b/cmd/root.go +index 148f65a..9b10937 100644 +--- a/cmd/root.go ++++ b/cmd/root.go +@@ -19,7 +19,8 @@ import ( + "os" + + "github.com/Nordgedanken/Morpheusv2/pkg/app" +- dbImpl "github.com/Nordgedanken/Morpheusv2/pkg/db/implementation" ++ "github.com/Nordgedanken/Morpheusv2/pkg/db/sqlite" ++ "github.com/Nordgedanken/Morpheusv2/pkg/util" + "github.com/shibukawa/configdir" + "github.com/spf13/cobra" + "io" +@@ -47,7 +48,7 @@ var rootCmd = &cobra.Command{ + } + + // os.OpenFile opens the file where the log is supposed to be written to +- logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) ++ logFile, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0600) + if err != nil { + return err + } +@@ -59,7 +60,8 @@ var rootCmd = &cobra.Command{ + log.SetOutput(mw) + + // dbImpl.Init() generates the needed tables if needed before the app starts +- err = dbImpl.Init() ++ util.DB = &sqlite.SQLite{} ++ err = util.DB.Init() + if err != nil { + return err + } +diff --git a/pkg/app/main.go b/pkg/app/main.go +index 3832900..255f074 100644 +--- a/pkg/app/main.go ++++ b/pkg/app/main.go +@@ -15,7 +15,10 @@ + package app + + import ( ++ "database/sql" ++ "github.com/Nordgedanken/Morpheusv2/pkg/loginUI" + "github.com/Nordgedanken/Morpheusv2/pkg/mainUI" ++ "github.com/Nordgedanken/Morpheusv2/pkg/util" + "github.com/matrix-org/gomatrix" + "github.com/therecipe/qt/core" + "github.com/therecipe/qt/gui" +@@ -36,11 +39,20 @@ func Start(argsArg []string) error { + + initApp() + +- mainUIS := mainUI.NewMainUI(windowWidth, windowHeight, window) +- SetNewWindow(mainUIS, window) ++ _, err := util.DB.GetCurrentUser() ++ // We special case ErrNoRows because this is expected to happen if user is missing ++ if err == sql.ErrNoRows { ++ loginUIs := loginUI.NewLoginUI(windowWidth, windowHeight, window) ++ SetNewWindow(loginUIs, window) ++ } else if err != nil { ++ return err ++ } else { ++ mainUIs := mainUI.NewMainUI(windowWidth, windowHeight, window) ++ SetNewWindow(mainUIs, window) ++ } + + widgets.QApplication_Exec() +- ++ + return nil + } + +@@ -65,7 +77,7 @@ func initApp() { + window.Resize2(windowWidth, windowHeight) + window.Move2(windowX, windowY) + +- app.ConnectQuit(func() { ++ window.ConnectCloseEvent(func(event *gui.QCloseEvent) { + log.Println("Morpheus closed") + }) + +diff --git a/pkg/app/ui.go b/pkg/app/ui.go +index 37ced17..7273079 100644 +--- a/pkg/app/ui.go ++++ b/pkg/app/ui.go +@@ -1,3 +1,17 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ + package app + + import ( +diff --git a/pkg/db/db.go b/pkg/db/db.go +index 0ffaede..27f04b8 100644 +--- a/pkg/db/db.go ++++ b/pkg/db/db.go +@@ -1,14 +1,37 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ + package db + +-import "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++import ( ++ "database/sql" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++) + + // DB defines a Interface to allow multiple DB Implementations + type DB interface { ++ Init() error ++ Open() *sql.DB ++ + SaveRoom(Room matrix.Room) error +- GetRooms() (rooms map[string]matrix.Room, err error) +- GetRoom(roomID string) (room matrix.Room, err error) ++ GetRooms() (roomsR []matrix.Room, err error) ++ GetRoom(roomID string) (roomR matrix.Room, err error) + + SaveUser(user matrix.User) error +- GetUsers() (map[string]matrix.User, error) +- GetCurrentUser() (matrix.User, error) ++ GetUser(userID string) (userR matrix.User, err error) ++ GetCurrentUser() (userR matrix.User, err error) ++ ++ SaveMessage(message matrix.Message) error ++ GetMessage(eventID string) (messageR matrix.Message, err error) + } +diff --git a/pkg/db/sqlite/db.go b/pkg/db/sqlite/db.go +new file mode 100644 +index 0000000..fa80421 +--- /dev/null ++++ b/pkg/db/sqlite/db.go +@@ -0,0 +1,62 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package sqlite ++ ++import ( ++ "database/sql" ++ "fmt" ++ _ "github.com/mattn/go-sqlite3" // Go-sqlite3 side effect import needed to use SQLite3 databases ++ "github.com/shibukawa/configdir" ++ "log" ++ "path/filepath" ++) ++ ++// Init prepares the DB by opening it and creating the required tables if needed ++func (s *SQLite) Init() (err error) { ++ log.Println("Start setting up DB") ++ var openErr error ++ ++ // Open the data.db file. It will be created if it doesn't exist. ++ configDirs := configdir.New("Nordgedanken", "Morpheusv2") ++ filePath := filepath.ToSlash(configDirs.QueryFolders(configdir.Global)[0].Path) ++ ++ log.Println("DBFilePath: ", filePath+"/data.db") ++ s.db, openErr = sql.Open("sqlite3", filePath+"/data.db") ++ if openErr != nil { ++ err = openErr ++ return ++ } ++ ++ log.Println("Creating DB Tables if needed") ++ createTables := `CREATE TABLE IF NOT EXISTS users (id varchar not null primary key, display_name text, avatar text, access_token text, own integer); ++ CREATE TABLE IF NOT EXISTS messages (id varchar not null primary key, author_id varchar, message text, timestamp datetime, pure_event text); ++ 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); ++ ` ++ _, execErr := s.db.Exec(createTables) ++ if execErr != nil { ++ err = fmt.Errorf("DB EXEC ERR: %s", execErr) ++ return ++ } ++ log.Println("Finished setting DB Setup") ++ return ++} ++ ++// Open returns the in Init() created db variable ++func (s *SQLite) Open() *sql.DB { ++ if s.db != nil { ++ return s.db ++ } ++ return nil ++} +diff --git a/pkg/db/sqlite/messages.go b/pkg/db/sqlite/messages.go +new file mode 100644 +index 0000000..6b709d7 +--- /dev/null ++++ b/pkg/db/sqlite/messages.go +@@ -0,0 +1,93 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package sqlite ++ ++import ( ++ "encoding/json" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix/messages" ++ "github.com/matrix-org/gomatrix" ++ "time" ++) ++ ++// SaveMessage saves message Events to the DB ++func (s *SQLite) SaveMessage(message matrix.Message) error { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ tx, err := s.db.Begin() ++ if err != nil { ++ return err ++ } ++ ++ stmt, err := tx.Prepare("INSERT INTO messages (id, author_id, message, timestamp, pure_event) VALUES (?, ?, ?, ?, ?)") ++ if err != nil { ++ return err ++ } ++ defer stmt.Close() ++ ++ id := message.GetEventID() ++ authorID := message.GetAuthorMXID() ++ messageS := message.GetMessage() ++ timestampR := message.GetTimestamp() ++ timestamp := timestampR.Format("2006-01-02 15:04:05") ++ pureEvent := message.GetEvent() ++ _, err = stmt.Exec(id, authorID, messageS, timestamp, pureEvent) ++ if err != nil { ++ return err ++ } ++ ++ return tx.Commit() ++} ++ ++// GetMessage returns the Message where the id matches the eventID ++func (s *SQLite) GetMessage(eventID string) (messageR matrix.Message, err error) { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ stmt, err := s.db.Prepare(`SELECT author_id, message, timestamp, pure_event FROM messages WHERE id=$1`) ++ if err != nil { ++ return ++ } ++ defer stmt.Close() ++ ++ row := stmt.QueryRow(eventID) ++ ++ var authorID string ++ var messageS string ++ var timestamp time.Time ++ var pureEvent string ++ err = row.Scan(&authorID, &messageS, &timestamp, &pureEvent) ++ if err != nil { ++ return ++ } ++ ++ messageI := &messages.Message{} ++ messageI.SetEventID(eventID) ++ messageI.SetAuthorMXID(authorID) ++ messageI.SetMessage(messageS) ++ messageI.SetTimestamp(&timestamp) ++ var gomatrixEvent gomatrix.Event ++ err = json.Unmarshal([]byte(pureEvent), &gomatrixEvent) ++ if err != nil { ++ return ++ } ++ messageI.SetEvent(&gomatrixEvent) ++ ++ messageR = messageI ++ return ++} +diff --git a/pkg/db/sqlite/rooms.go b/pkg/db/sqlite/rooms.go +new file mode 100644 +index 0000000..1bfd627 +--- /dev/null ++++ b/pkg/db/sqlite/rooms.go +@@ -0,0 +1,172 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package sqlite ++ ++import ( ++ "encoding/json" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix/rooms" ++) ++ ++// SaveRoom saves a Room into the sqlite DB ++func (s *SQLite) SaveRoom(Room matrix.Room) error { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ tx, err := s.db.Begin() ++ if err != nil { ++ return err ++ } ++ ++ stmt, err := tx.Prepare("INSERT INTO rooms (room_aliases, id, room_name, room_avatar, room_topic, room_messages) VALUES (?, ?, ?, ?, ?, ?)") ++ if err != nil { ++ return err ++ } ++ defer stmt.Close() ++ ++ aliases := Room.GetRoomAliases() ++ aliasesBytes, err := json.Marshal(aliases) ++ if err != nil { ++ return err ++ } ++ aliasesS := string(aliasesBytes) ++ roomID := Room.GetRoomID() ++ name, err := Room.GetName() ++ if err != nil { ++ return err ++ } ++ avatar, err := Room.GetAvatar() ++ if err != nil { ++ return err ++ } ++ topic, err := Room.GetTopic() ++ if err != nil { ++ return err ++ } ++ ++ messages := Room.GetMessages() ++ if err != nil { ++ return err ++ } ++ var messageIDs []string ++ for _, v := range messages { ++ messageIDs = append(messageIDs, v.GetEventID()) ++ } ++ ++ _, err = stmt.Exec(aliasesS, roomID, name, string(avatar), topic, messageIDs) ++ if err != nil { ++ return err ++ } ++ return tx.Commit() ++} ++ ++// GetRooms returns all Rooms from the Database ++func (s *SQLite) GetRooms() (roomsR []matrix.Room, err error) { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ rows, err := s.db.Query("SELECT id, room_aliases, room_name, room_avatar, room_topic, room_messages FROM rooms") ++ if err != nil { ++ return ++ } ++ defer rows.Close() ++ ++ for rows.Next() { ++ var roomID string ++ var roomAliases string ++ var roomName string ++ var roomAvatar string ++ var roomTopic string ++ var roomMessages string ++ err = rows.Scan(&roomID, &roomAliases, &roomName, &roomAvatar, &roomTopic, &roomMessages) ++ if err != nil { ++ return ++ } ++ ++ roomI := &rooms.Room{} ++ roomI.SetRoomID(roomID) ++ var aliases []string ++ err = json.Unmarshal([]byte(roomAliases), &aliases) ++ if err != nil { ++ return ++ } ++ roomI.SetRoomAliases(aliases) ++ roomI.SetName(roomName) ++ roomI.SetAvatar([]byte(roomAvatar)) ++ roomI.SetTopic(roomTopic) ++ var messageIDs []string ++ err = json.Unmarshal([]byte(roomMessages), &messageIDs) ++ if err != nil { ++ return ++ } ++ // TODO Convert IDs to messages slice using another call or from the beginning on using a JOIN ++ //roomI.SetMessages(messages) ++ ++ roomsR = append(roomsR, roomI) ++ } ++ ++ // get any error encountered during iteration ++ err = rows.Err() ++ return ++} ++ ++// GetRoom returns the Room where the id matches the roomID ++func (s *SQLite) GetRoom(roomID string) (roomR matrix.Room, err error) { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ stmt, err := s.db.Prepare(`SELECT room_aliases, room_name, room_avatar, room_topic, room_messages FROM rooms WHERE id=$1`) ++ if err != nil { ++ return ++ } ++ defer stmt.Close() ++ ++ row := stmt.QueryRow(roomID) ++ ++ var roomAliases string ++ var roomName string ++ var roomAvatar string ++ var roomTopic string ++ var roomMessages string ++ err = row.Scan(&roomAliases, &roomName, &roomAvatar, &roomTopic, &roomMessages) ++ if err != nil { ++ return ++ } ++ ++ roomI := &rooms.Room{} ++ roomI.SetRoomID(roomID) ++ var aliases []string ++ err = json.Unmarshal([]byte(roomAliases), &aliases) ++ if err != nil { ++ return ++ } ++ roomI.SetRoomAliases(aliases) ++ roomI.SetName(roomName) ++ roomI.SetAvatar([]byte(roomAvatar)) ++ roomI.SetTopic(roomTopic) ++ var messageIDs []string ++ err = json.Unmarshal([]byte(roomMessages), &messageIDs) ++ if err != nil { ++ return ++ } ++ // TODO Convert IDs to messages slice using another call or from the beginning on using a JOIN ++ //roomI.SetMessages(messages) ++ ++ roomR = roomI ++ return ++} +diff --git a/pkg/db/sqlite/struct.go b/pkg/db/sqlite/struct.go +new file mode 100644 +index 0000000..6497773 +--- /dev/null ++++ b/pkg/db/sqlite/struct.go +@@ -0,0 +1,22 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package sqlite ++ ++import "database/sql" ++ ++// SQLite implements a SQLite database for the db.DB interface ++type SQLite struct { ++ db *sql.DB ++} +diff --git a/pkg/db/sqlite/users.go b/pkg/db/sqlite/users.go +new file mode 100644 +index 0000000..e78a6a6 +--- /dev/null ++++ b/pkg/db/sqlite/users.go +@@ -0,0 +1,125 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package sqlite ++ ++import ( ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix/users" ++ "github.com/matrix-org/gomatrix" ++ "strings" ++) ++ ++// SaveUser saves a matrix User to the User table ++func (s *SQLite) SaveUser(user matrix.User) error { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ tx, err := s.db.Begin() ++ if err != nil { ++ return err ++ } ++ ++ stmt, err := tx.Prepare("INSERT INTO users (id, display_name, avatar) VALUES (?, ?, ?)") ++ if err != nil { ++ return err ++ } ++ defer stmt.Close() ++ displayName, err := user.GetDisplayName("") ++ if err != nil { ++ return err ++ } ++ avatar, err := user.GetAvatar("") ++ if err != nil { ++ return err ++ } ++ mxid := user.GetMXID() ++ _, err = stmt.Exec(mxid, displayName, string(avatar)) ++ if err != nil { ++ return err ++ } ++ ++ return tx.Commit() ++} ++ ++// GetCurrentUser returns the current user including a ready gomatrix client ++func (s *SQLite) GetCurrentUser() (userR matrix.User, err error) { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ stmt, err := s.db.Prepare(`SELECT id, display_name, avatar, access_token FROM users WHERE own=1`) ++ if err != nil { ++ return ++ } ++ defer stmt.Close() ++ ++ row := stmt.QueryRow() ++ ++ var mxid string ++ var displayName string ++ var avatar string ++ var accessToken string ++ err = row.Scan(&mxid, &displayName, &avatar, &accessToken) ++ if err != nil { ++ return ++ } ++ ++ userI := &users.User{} ++ userI.SetMXID(mxid) ++ userI.SetDisplayName("", displayName) ++ userI.SetAvatar("", []byte(avatar)) ++ ++ splitUser := strings.Split(mxid, ":") ++ domain := strings.TrimPrefix(mxid, splitUser[0]+":") ++ client, err := gomatrix.NewClient(domain, mxid, accessToken) ++ if err != nil { ++ return ++ } ++ userI.SetCli(client) ++ ++ userR = userI ++ return ++} ++ ++// GetUser returns a user matching the mxid of the argument ++func (s *SQLite) GetUser(userID string) (userR matrix.User, err error) { ++ if s.db == nil { ++ s.db = s.Open() ++ } ++ ++ stmt, err := s.db.Prepare(`SELECT display_name, avatar FROM users WHERE id=$1`) ++ if err != nil { ++ return ++ } ++ defer stmt.Close() ++ ++ row := stmt.QueryRow(userID) ++ ++ var displayName string ++ var avatar string ++ err = row.Scan(&displayName, &avatar) ++ if err != nil { ++ return ++ } ++ ++ userI := &users.User{} ++ userI.SetMXID(userID) ++ userI.SetDisplayName("", displayName) ++ userI.SetAvatar("", []byte(avatar)) ++ ++ userR = userI ++ return ++} +diff --git a/pkg/loginUI/loginUI.go b/pkg/loginUI/loginUI.go +new file mode 100644 +index 0000000..fa3d993 +--- /dev/null ++++ b/pkg/loginUI/loginUI.go +@@ -0,0 +1,77 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package loginUI ++ ++import ( ++ "github.com/matrix-org/gomatrix" ++ "github.com/therecipe/qt/core" ++ "github.com/therecipe/qt/gui" ++ "github.com/therecipe/qt/uitools" ++ "github.com/therecipe/qt/widgets" ++) ++ ++// LoginUI defines the data for the login ui ++type LoginUI struct { ++ widget *widgets.QWidget ++ cli *gomatrix.Client ++ window *widgets.QMainWindow ++ windowWidth int ++ windowHeight int ++} ++ ++// NewLoginUI gives you a MainUI struct with profiled data ++func NewLoginUI(windowWidth, windowHeight int, window *widgets.QMainWindow) (loginUI *LoginUI) { ++ loginUI = &LoginUI{ ++ windowWidth: windowWidth, ++ windowHeight: windowHeight, ++ window: window, ++ } ++ return ++} ++ ++// SetCli sets the gomatrix Client for the LoginUI ++func (m *LoginUI) SetCli(cli *gomatrix.Client) { ++ m.cli = cli ++} ++ ++// GetWidget returns the QWidget of the LoginUI ++func (m *LoginUI) GetWidget() (widget *widgets.QWidget) { ++ return m.widget ++} ++ ++// NewUI prepares the new UI ++func (m *LoginUI) NewUI() error { ++ m.widget = widgets.NewQWidget(nil, 0) ++ ++ var loader = uitools.NewQUiLoader(nil) ++ var file = core.NewQFile2(":/qml/ui/login.ui") ++ ++ file.Open(core.QIODevice__ReadOnly) ++ mainWidget := loader.Load(file, m.widget) ++ file.Close() ++ ++ var layout = widgets.NewQHBoxLayout() ++ m.window.SetLayout(layout) ++ layout.InsertWidget(0, mainWidget, 0, core.Qt__AlignTop|core.Qt__AlignLeft) ++ layout.SetSpacing(0) ++ layout.SetContentsMargins(0, 0, 0, 0) ++ ++ m.widget.ConnectResizeEvent(func(event *gui.QResizeEvent) { ++ mainWidget.Resize(event.Size()) ++ event.Accept() ++ }) ++ ++ return nil ++} +diff --git a/pkg/mainUI/mainUI.go b/pkg/mainUI/mainUI.go +index 7fcaaf9..a8cddc3 100644 +--- a/pkg/mainUI/mainUI.go ++++ b/pkg/mainUI/mainUI.go +@@ -1,3 +1,17 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ + package mainUI + + import ( +diff --git a/pkg/matrix/dataTypes.go b/pkg/matrix/dataTypes.go +index 8d30e68..a010373 100644 +--- a/pkg/matrix/dataTypes.go ++++ b/pkg/matrix/dataTypes.go +@@ -1,3 +1,17 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ + package matrix + + import ( +@@ -9,8 +23,15 @@ import ( + type User interface { + SetCli(cli *gomatrix.Client) + SetMXID(id string) ++ SetDisplayName(roomID string, name string) ++ SetAvatar(roomID string, avatar []byte) ++ ++ GetMXID() string + GetDisplayName(roomID string) (string, error) +- GetAvatar(roomID string) (string, error) ++ GetAvatar(roomID string) ([]byte, error) ++ GetCli() (cli *gomatrix.Client) ++ ++ //Implement MarshalJSON() (b []byte, e error) as in http://gregtrowbridge.com/golang-json-serialization-with-interfaces/ to support json + } + + // Room defines a Interface to allow multiple Room type Implementations +@@ -18,11 +39,20 @@ type Room interface { + // Handled using global "own User" + //SetCli(cli *gomatrix.Client) + SetRoomID(id string) +- SetRoomAliases(aliases map[int64]string) ++ SetRoomAliases(aliases []string) ++ SetName(name string) ++ SetAvatar(avatar []byte) ++ SetTopic(topic string) ++ SetMessages(messages []Message) ++ ++ GetRoomID() string ++ GetRoomAliases() []string + GetName() (string, error) +- GetAvatar() (string, error) ++ GetAvatar() ([]byte, error) + GetTopic() (string, error) +- GetMessages() (map[string]Message, error) ++ GetMessages() []Message ++ ++ //Implement MarshalJSON() (b []byte, e error) as in http://gregtrowbridge.com/golang-json-serialization-with-interfaces/ to support json + } + + // Message defines a Interface to allow multiple Message type Implementations +@@ -34,5 +64,14 @@ type Message interface { + SetAuthorMXID(mxid string) + SetMessage(message string) + SetTimestamp(ts *time.Time) ++ ++ GetEventID() (id string) ++ GetEvent() (event *gomatrix.Event) ++ GetAuthorMXID() (mxid string) ++ GetMessage() (message string) ++ GetTimestamp() (ts *time.Time) ++ + Show() error ++ ++ //Implement MarshalJSON() (b []byte, e error) as in http://gregtrowbridge.com/golang-json-serialization-with-interfaces/ to support json + } +diff --git a/pkg/matrix/messages/message.go b/pkg/matrix/messages/message.go +new file mode 100644 +index 0000000..186fdda +--- /dev/null ++++ b/pkg/matrix/messages/message.go +@@ -0,0 +1,85 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package messages ++ ++import ( ++ "github.com/matrix-org/gomatrix" ++ "time" ++) ++ ++// Message holds the needed Message data and allows to work with that. It gets normally loaded from the cache ++type Message struct { ++ eventID string ++ event *gomatrix.Event ++ authorID string ++ text string ++ timestamp *time.Time ++} ++ ++// SetEventID adds the eventID to the current Message ++func (m *Message) SetEventID(id string) { ++ m.eventID = id ++} ++ ++// SetEvent adds the gomatrix Event to the current Message ++func (m *Message) SetEvent(event *gomatrix.Event) { ++ m.event = event ++} ++ ++// SetAuthorMXID adds the author MXID to the current Message ++func (m *Message) SetAuthorMXID(mxid string) { ++ m.authorID = mxid ++} ++ ++// SetMessage adds the message Text to the current Message ++func (m *Message) SetMessage(message string) { ++ m.text = message ++} ++ ++// SetTimestamp adds the Timestamp to the current Message ++func (m *Message) SetTimestamp(ts *time.Time) { ++ m.timestamp = ts ++} ++ ++// GetEventID returns the event ID from the current Message ++func (m *Message) GetEventID() (id string) { ++ return m.eventID ++} ++ ++// GetEvent returns the gomatrix event from the current Message ++func (m *Message) GetEvent() (event *gomatrix.Event) { ++ return m.event ++} ++ ++// GetAuthorMXID returns the authors mxid from the current Message ++func (m *Message) GetAuthorMXID() (mxid string) { ++ return m.authorID ++} ++ ++// GetMessage returns the text from the current Message ++func (m *Message) GetMessage() (message string) { ++ return m.text ++} ++ ++// GetTimestamp returns the timestamp from the current Message ++func (m *Message) GetTimestamp() (ts *time.Time) { ++ return m.timestamp ++} ++ ++// Show adds the current Message to the UI ++// TODO implement it ++func (m *Message) Show() error { ++ return nil ++} +diff --git a/pkg/matrix/rooms/room.go b/pkg/matrix/rooms/room.go +new file mode 100644 +index 0000000..9d884ce +--- /dev/null ++++ b/pkg/matrix/rooms/room.go +@@ -0,0 +1,145 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package rooms ++ ++import ( ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++ "github.com/Nordgedanken/Morpheusv2/pkg/util" ++ "github.com/matrix-org/gomatrix" ++ "strings" ++) ++ ++// Room holds the needed Room data and allows to work with that. It gets normally loaded from the cache ++type Room struct { ++ id string ++ aliases []string ++ name string ++ avatar []byte ++ topic string ++ messages []matrix.Message ++} ++ ++// SetRoomID adds the roomID to the current Room ++func (r *Room) SetRoomID(id string) { ++ r.id = id ++} ++ ++// SetRoomAliases adds the aliases to the current Room ++func (r *Room) SetRoomAliases(aliases []string) { ++ r.aliases = aliases ++} ++ ++// SetName adds the name to the current Room ++func (r *Room) SetName(name string) { ++ r.name = name ++} ++ ++// SetAvatar adds the avatar to the current Room ++func (r *Room) SetAvatar(avatar []byte) { ++ r.avatar = avatar ++} ++ ++// SetTopic adds the topic to the current Room ++func (r *Room) SetTopic(topic string) { ++ r.topic = topic ++} ++ ++// SetMessages adds the messages to the current Room ++func (r *Room) SetMessages(messages []matrix.Message) { ++ r.messages = messages ++} ++ ++// GetRoomID returns the room ID from the current Room ++func (r *Room) GetRoomID() string { ++ return r.id ++} ++ ++// GetRoomAliases returns the room aliases from the current Room ++func (r *Room) GetRoomAliases() []string { ++ return r.aliases ++} ++ ++// GetName returns the name from the current Room ++func (r *Room) GetName() (string, error) { ++ if r.name == "" { ++ type RespRoomName struct { ++ Name string `json:"name"` ++ } ++ resp := &RespRoomName{} ++ err := util.User.GetCli().StateEvent(r.id, "m.room.name", "", resp) ++ if err != nil { ++ return "", err ++ } ++ r.name = resp.Name ++ } ++ return r.name, nil ++} ++ ++// GetAvatar returns the avatar from the current Room ++func (r *Room) GetAvatar() ([]byte, error) { ++ if r.avatar == nil { ++ resp := &gomatrix.Event{} ++ err := util.User.GetCli().StateEvent(r.id, "m.room.avatar", "", resp) ++ if err != nil { ++ return nil, err ++ } ++ var avatar []byte ++ value, exists := resp.Content["url"] ++ if !exists { ++ return nil, nil ++ } ++ url, ok := value.(string) ++ if !ok { ++ return nil, nil ++ } ++ split := strings.Split(url, "/") ++ servername := strings.TrimPrefix(split[0], "mxc://") ++ mediaID := split[1] ++ mediaURL := util.User.GetCli().BuildBaseURL("_matrix/media/r0/download", servername, mediaID) ++ avatar, err = util.User.GetCli().MakeRequest("GET", mediaURL, nil, nil) ++ if err != nil { ++ return nil, err ++ } ++ r.avatar = avatar ++ } ++ return r.avatar, nil ++} ++ ++// GetTopic returns the topic from the current Room ++func (r *Room) GetTopic() (string, error) { ++ if r.topic == "" { ++ resp := &gomatrix.Event{} ++ err := util.User.GetCli().StateEvent(r.id, "m.room.topic", "", resp) ++ if err != nil { ++ return "", err ++ } ++ value, exists := resp.Content["topic"] ++ if !exists { ++ return "", nil ++ } ++ topic, ok := value.(string) ++ if !ok { ++ return "", nil ++ } ++ r.topic = topic ++ } ++ return r.topic, nil ++} ++ ++// GetMessages returns the messages from the current Room ++func (r *Room) GetMessages() []matrix.Message { ++ // TODO Lazy load from DB ++ return r.messages ++} +diff --git a/pkg/matrix/users/user.go b/pkg/matrix/users/user.go +new file mode 100644 +index 0000000..8cee5cf +--- /dev/null ++++ b/pkg/matrix/users/user.go +@@ -0,0 +1,127 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package users ++ ++import ( ++ "github.com/Nordgedanken/Morpheusv2/pkg/util" ++ "github.com/matrix-org/gomatrix" ++ "strings" ++) ++ ++// User holds the needed User data and allows to work with that. It gets normally loaded from the cache ++type User struct { ++ cli *gomatrix.Client ++ mxid string ++ defaultDisplayName string ++ displayName map[string]string ++ defaultAvatar []byte ++ avatar map[string][]byte ++} ++ ++// 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. ++func (u *User) SetCli(cli *gomatrix.Client) { ++ u.cli = cli ++} ++ ++// SetMXID adds the mxid to the current User ++func (u *User) SetMXID(id string) { ++ u.mxid = id ++} ++ ++// SetDisplayName adds the displayName to the current User ++func (u *User) SetDisplayName(roomID string, name string) { ++ if roomID == "" { ++ u.defaultDisplayName = name ++ } else { ++ if u.displayName == nil { ++ u.displayName = make(map[string]string) ++ } ++ u.displayName[roomID] = name ++ } ++} ++ ++// SetAvatar adds the avatar to the current User ++func (u *User) SetAvatar(roomID string, avatar []byte) { ++ if roomID == "" { ++ u.defaultAvatar = avatar ++ } else { ++ if u.avatar == nil { ++ u.avatar = make(map[string][]byte) ++ } ++ u.avatar[roomID] = avatar ++ } ++} ++ ++// GetMXID returns the mxid from the current User ++func (u *User) GetMXID() string { ++ return u.mxid ++} ++ ++// GetDisplayName returns the displayName from the current User ++func (u *User) GetDisplayName(roomID string) (string, error) { ++ if roomID == "" { ++ if u.defaultDisplayName == "" { ++ resp, err := util.User.GetCli().GetDisplayName(u.mxid) ++ if err != nil { ++ return "", err ++ } ++ u.defaultDisplayName = resp.DisplayName ++ } ++ return u.defaultDisplayName, nil ++ } ++ // TODO get Membership Event from Room instead returning default directly ++ if u.displayName[roomID] == "" { ++ return u.defaultDisplayName, nil ++ } ++ return u.displayName[roomID], nil ++} ++ ++// GetAvatar returns the avatar from the current User ++func (u *User) GetAvatar(roomID string) ([]byte, error) { ++ if roomID == "" { ++ if u.defaultAvatar == nil { ++ urlPath := util.User.GetCli().BuildURL("profile", u.mxid, "avatar_url") ++ s := struct { ++ AvatarURL string `json:"avatar_url"` ++ }{} ++ ++ _, err := util.User.GetCli().MakeRequest("GET", urlPath, nil, &s) ++ if err != nil { ++ return nil, err ++ } ++ ++ split := strings.Split(s.AvatarURL, "/") ++ servername := strings.TrimPrefix(split[0], "mxc://") ++ mediaID := split[1] ++ mediaURL := util.User.GetCli().BuildBaseURL("_matrix/media/r0/download", servername, mediaID) ++ avatar, err := util.User.GetCli().MakeRequest("GET", mediaURL, nil, nil) ++ if err != nil { ++ return nil, err ++ } ++ u.defaultAvatar = avatar ++ } ++ return u.defaultAvatar, nil ++ } ++ // TODO get Membership Event from Room instead returning default directly ++ if u.avatar[roomID] == nil { ++ return u.defaultAvatar, nil ++ } ++ return u.avatar[roomID], nil ++} ++ ++// GetCli returns the gomatrix.Client from the current User ++func (u *User) GetCli() *gomatrix.Client { ++ return u.cli ++} +diff --git a/pkg/util/vars.go b/pkg/util/vars.go +new file mode 100644 +index 0000000..7325755 +--- /dev/null ++++ b/pkg/util/vars.go +@@ -0,0 +1,26 @@ ++// Copyright © 2018 MTRNord <info@nordgedanken.de> ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++package util ++ ++import ( ++ "github.com/Nordgedanken/Morpheusv2/pkg/db" ++ "github.com/Nordgedanken/Morpheusv2/pkg/matrix" ++) ++ ++// DB holds the main pointer to the Database ++var DB db.DB ++ ++// User holds the Current User ++var User matrix.User diff --git a/pulls/7.json b/pulls/7.json @@ -0,0 +1,18 @@ +{ + "number": 7, + "title": "Merge master back into develop", + "state": "merged", + "diff_file": "7.diff", + "author": "MTRNord", + "created_at": "2018-05-05T23:12:22Z", + "closed_at": "2018-05-05T23:12:38Z", + "merged_at": "2018-05-05T23:12:38Z", + "base_ref": "develop", + "head_ref": "master", + "labels": [], + "assignees": [], + "requested_reviewers": [], + "body": "", + "comments": [], + "review_comments": [] +} diff --git a/pulls/7.md b/pulls/7.md @@ -0,0 +1,13 @@ +# PR #7 Merge master back into develop + +- **Status:** merged +- **Author:** @MTRNord +- **Created:** 2018-05-05T23:12:22Z +- **Branch:** master → develop +- **Merged:** 2018-05-05T23:12:38Z +- **Diff:** [7.diff](./7.diff) + +--- + +_No description._ + diff --git a/pulls/8.diff b/pulls/8.diff @@ -0,0 +1,70 @@ +diff --git a/pkg/app/main.go b/pkg/app/main.go +index 255f074..3b7aa0e 100644 +--- a/pkg/app/main.go ++++ b/pkg/app/main.go +@@ -52,7 +52,7 @@ func Start(argsArg []string) error { + } + + widgets.QApplication_Exec() +- ++ + return nil + } + +diff --git a/pkg/db/implementation/db.go b/pkg/db/implementation/db.go +deleted file mode 100644 +index 9429d4b..0000000 +--- a/pkg/db/implementation/db.go ++++ /dev/null +@@ -1,51 +0,0 @@ +-package implementation +- +-import ( +- "database/sql" +- "fmt" +- _ "github.com/mattn/go-sqlite3" // Go-sqlite3 side effect import needed to use SQLite3 databases +- "github.com/shibukawa/configdir" +- "log" +- "path/filepath" +-) +- +-var db *sql.DB +- +-// Init prepares the DB by opening it and creating the required tables if needed +-// TODO: Make part of the interface +-func Init() (err error) { +- log.Println("Start setting up DB") +- var openErr error +- +- // Open the data.db file. It will be created if it doesn't exist. +- configDirs := configdir.New("Nordgedanken", "Morpheusv2") +- filePath := filepath.ToSlash(configDirs.QueryFolders(configdir.Global)[0].Path) +- +- log.Println("DBFilePath: ", filePath+"/data.db") +- db, openErr = sql.Open("sqlite3", filePath+"/data.db") +- if openErr != nil { +- err = openErr +- return +- } +- +- log.Println("Creating DB Tables if needed") +- createTables := `CREATE TABLE IF NOT EXISTS users (id integer not null primary key, display_name text, avatar text); +- CREATE TABLE IF NOT EXISTS messages (id integer not null primary key, author text, message text, timestamp text, pure_event text); +- CREATE TABLE IF NOT EXISTS rooms (id integer not null primary key, room_aliases text, room_id text, room_name text, room_avatar text, room_topic text, room_messages text); +- ` +- _, execErr := db.Exec(createTables) +- if execErr != nil { +- err = fmt.Errorf("DB EXEC ERR: %s", execErr) +- return +- } +- log.Println("Finished setting DB Setup") +- return +-} +- +-// Open returns the in Init() created db variable +-func Open() *sql.DB { +- if db != nil { +- return db +- } +- return nil +-} diff --git a/pulls/8.json b/pulls/8.json @@ -0,0 +1,20 @@ +{ + "number": 8, + "title": "Remove weird whitespace and cleanup Code", + "state": "merged", + "diff_file": "8.diff", + "author": "MTRNord", + "created_at": "2018-05-05T23:18:23Z", + "closed_at": "2018-05-05T23:18:31Z", + "merged_at": "2018-05-05T23:18:31Z", + "base_ref": "master", + "head_ref": "develop", + "labels": [ + "enhancement" + ], + "assignees": [], + "requested_reviewers": [], + "body": "", + "comments": [], + "review_comments": [] +} diff --git a/pulls/8.md b/pulls/8.md @@ -0,0 +1,14 @@ +# PR #8 Remove weird whitespace and cleanup Code + +- **Status:** merged +- **Author:** @MTRNord +- **Created:** 2018-05-05T23:18:23Z +- **Branch:** develop → master +- **Merged:** 2018-05-05T23:18:31Z +- **Labels:** enhancement +- **Diff:** [8.diff](./8.diff) + +--- + +_No description._ +