diff --git a/api/client-server/definitions/room_event_filter.yaml b/api/client-server/definitions/room_event_filter.yaml index a3bb6852..7d9184b5 100644 --- a/api/client-server/definitions/room_event_filter.yaml +++ b/api/client-server/definitions/room_event_filter.yaml @@ -28,4 +28,8 @@ properties: items: type: string type: array + contains_url: + type: boolean + description: If ``true``, includes only events with a url key in their content. If + ``false``, excludes those events. type: object diff --git a/api/client-server/message_pagination.yaml b/api/client-server/message_pagination.yaml index 853e0ec3..005b8fb3 100644 --- a/api/client-server/message_pagination.yaml +++ b/api/client-server/message_pagination.yaml @@ -75,6 +75,13 @@ paths: description: |- The maximum number of events to return. Default: 10. x-example: "3" + - in: query + type: string + name: filter + description: |- + A JSON RoomEventFilter to filter returned events with. + x-example: |- + {"contains_url":true} responses: 200: description: A list of messages with a new token to request more. diff --git a/changelogs/client_server.rst b/changelogs/client_server.rst index 7a8536e3..f156c96e 100644 --- a/changelogs/client_server.rst +++ b/changelogs/client_server.rst @@ -23,6 +23,8 @@ (`#376 `_). - Correct inconsistent specification of ``redacted_because`` fields and their values (`#378 `_). + - Mark required fields in response objects as such + (`#394 `_). - Changes to the API which will be backwards-compatible for clients: @@ -37,6 +39,10 @@ (`#380 `_). - Add ``is_direct`` flag to ``/createRoom``. (`#389 `_). + - Add ``contains_url`` option to ``RoomEventFilter``. + (`#390 `_). + - Add ``filter`` optional query param to ``/messages`` + (`#390 `_). r0.2.0 ====== diff --git a/scripts/speculator/main.go b/scripts/speculator/main.go index b433a327..87ee4bf6 100644 --- a/scripts/speculator/main.go +++ b/scripts/speculator/main.go @@ -27,6 +27,7 @@ import ( "strings" "sync" "syscall" + "text/template" "time" "github.com/hashicorp/golang-lru" @@ -83,19 +84,15 @@ func accessTokenQuerystring() string { return fmt.Sprintf("?access_token=%s", *accessToken) } -func gitClone(url string, shared bool) (string, error) { - directory := path.Join("/tmp/matrix-doc", strconv.FormatInt(rand.Int63(), 10)) - if err := os.MkdirAll(directory, permissionsOwnerFull); err != nil { - return "", fmt.Errorf("error making directory %s: %v", directory, err) - } +func gitClone(url string, directory string, shared bool) error { args := []string{"clone", url, directory} if shared { args = append(args, "--shared") } if err := runGitCommand(directory, args); err != nil { - return "", err + return err } - return directory, nil + return nil } func gitCheckout(path, sha string) error { @@ -159,6 +156,16 @@ func generate(dir string) error { if err := cmd.Run(); err != nil { return fmt.Errorf("error generating spec: %v\nOutput from gendoc:\n%v", err, b.String()) } + + // cheekily dump the swagger docs into the gen directory so they can be + // served by serveSpec + cmd = exec.Command("python", "dump-swagger.py", "gen/api-docs.json") + cmd.Dir = path.Join(dir, "scripts") + cmd.Stderr = &b + if err := cmd.Run(); err != nil { + return fmt.Errorf("error generating api docs: %v\nOutput from dump-swagger:\n%v", err, b.String()) + } + return nil } @@ -195,8 +202,14 @@ func (s *server) generateAt(sha string) (dst string, err error) { return } } + + dst, err = makeTempDir() + if err != nil { + return + } + log.Printf("Generating %s in %s\n", sha, dst) s.mu.Lock() - dst, err = gitClone(s.matrixDocCloneURL, true) + err = gitClone(s.matrixDocCloneURL, dst, true) s.mu.Unlock() if err != nil { return @@ -219,7 +232,7 @@ func (s *server) getSHAOf(ref string) (string, error) { err := cmd.Run() s.mu.Unlock() if err != nil { - return "", fmt.Errorf("error generating spec: %v\nOutput from gendoc:\n%v", err, b.String()) + return "", fmt.Errorf("error generating spec: %v\nOutput from git:\n%v", err, b.String()) } return strings.TrimSpace(b.String()), nil } @@ -396,6 +409,11 @@ func (s *server) serveSpec(w http.ResponseWriter, req *http.Request) { cache.Add(sha, pathToContent) } + if requestedPath == "api-docs.json" { + // allow other swagger UIs access to our swagger + w.Header().Set("Access-Control-Allow-Origin", "*") + } + if b, ok := pathToContent[requestedPath]; ok { w.Write(b) return @@ -588,12 +606,6 @@ func (srv *server) makeIndex(w http.ResponseWriter, req *http.Request) { writeError(w, 500, err) return } - s := "
    " - for _, pull := range pulls { - s += fmt.Sprintf(`
  • %d: %s: %s: spec spec diff rst diff
  • `, - pull.Number, pull.User.HTMLURL, pull.User.Login, pull.HTMLURL, pull.Title, pull.Number, pull.Number, pull.Number) - } - s += "
" branches, err := srv.getBranches() if err != nil { @@ -601,7 +613,48 @@ func (srv *server) makeIndex(w http.ResponseWriter, req *http.Request) { return } - s += `
View the spec at:
    ` + // write our stuff into a buffer so that we can change our minds + // and write a 500 if it all goes wrong. + var b bytes.Buffer + b.Write([]byte(` + + + +
      +`)) + + tmpl, err := template.New("pr entry").Parse(` +
    • {{.Number}}: + {{.User.Login}}: + {{.Title}}: + spec + api docs + spec diff + rst diff +
    • +`) + if err != nil { + log.Fatal(err) + } + + for _, pull := range pulls { + err = tmpl.Execute(&b, pull) + if err != nil { + writeError(w, 500, err) + return + } + } + b.Write([]byte(` +
    +
    View the spec at:
      +`)) branchNames := []string{} for _, branch := range branches { if strings.HasPrefix(branch, "drafts/") { @@ -611,15 +664,14 @@ func (srv *server) makeIndex(w http.ResponseWriter, req *http.Request) { branchNames = append(branchNames, "HEAD") for _, branch := range branchNames { href := "spec/" + url.QueryEscape(branch) + "/" - s += fmt.Sprintf(`
    • %s
    • `, href, branch) + fmt.Fprintf(&b, `
    • %s
    • `, href, branch) if *includesDir != "" { - s += fmt.Sprintf(`
    • %s, styled like matrix.org
    • `, + fmt.Fprintf(&b, `
    • %s, styled like matrix.org
    • `, href, branch) } } - s += "
    " - - io.WriteString(w, s) + b.Write([]byte("
")) + b.WriteTo(w) } func ignoreExitCodeOne(err error) error { @@ -655,10 +707,14 @@ func main() { log.Fatal(err) } rand.Seed(time.Now().Unix()) - masterCloneDir, err := gitClone(matrixDocCloneURL, false) + masterCloneDir, err := makeTempDir() if err != nil { log.Fatal(err) } + log.Printf("Creating master clone dir %s\n", masterCloneDir) + if err = gitClone(matrixDocCloneURL, masterCloneDir, false); err != nil { + log.Fatal(err) + } s := server{matrixDocCloneURL: masterCloneDir} http.HandleFunc("/spec/", forceHTML(s.serveSpec)) http.HandleFunc("/diff/rst/", s.serveRSTDiff) @@ -691,3 +747,11 @@ func initCache() error { styledSpecCache = c2 return err } + +func makeTempDir() (string, error) { + directory := path.Join("/tmp/matrix-doc", strconv.FormatInt(rand.Int63(), 10)) + if err := os.MkdirAll(directory, permissionsOwnerFull); err != nil { + return "", fmt.Errorf("error making directory %s: %v", directory, err) + } + return directory, nil +} diff --git a/supporting-docs/projects/2014-06-09-vector.md b/supporting-docs/projects/2014-06-09-vector.md index 3f49be69..4f0ea2f5 100644 --- a/supporting-docs/projects/2014-06-09-vector.md +++ b/supporting-docs/projects/2014-06-09-vector.md @@ -1,7 +1,6 @@ --- layout: project title: Try Matrix Now! -categories: projects client --- diff --git a/supporting-docs/projects/2015-04-03-vector-ios.md b/supporting-docs/projects/2015-04-03-vector-ios.md index 2d295483..11fc618e 100644 --- a/supporting-docs/projects/2015-04-03-vector-ios.md +++ b/supporting-docs/projects/2015-04-03-vector-ios.md @@ -1,7 +1,6 @@ --- layout: project title: Try Matrix Now! -categories: projects client --- diff --git a/supporting-docs/projects/2015-06-02-vector-android.md b/supporting-docs/projects/2015-06-02-vector-android.md index 0af7c7b1..9d4e585e 100644 --- a/supporting-docs/projects/2015-06-02-vector-android.md +++ b/supporting-docs/projects/2015-06-02-vector-android.md @@ -1,7 +1,6 @@ --- layout: project title: Try Matrix Now! -categories: projects client --- diff --git a/supporting-docs/projects/2016-02-06-vector-desktop.md b/supporting-docs/projects/2016-02-06-vector-desktop.md index f6664f81..7355ccfc 100644 --- a/supporting-docs/projects/2016-02-06-vector-desktop.md +++ b/supporting-docs/projects/2016-02-06-vector-desktop.md @@ -1,7 +1,6 @@ --- layout: project title: Vector Desktop -categories: projects client description: Desktop version of Vector author: Steven Hammerton maturity: Alpha diff --git a/templating/matrix_templates/units.py b/templating/matrix_templates/units.py index ee5b40a6..f362f63d 100644 --- a/templating/matrix_templates/units.py +++ b/templating/matrix_templates/units.py @@ -96,8 +96,7 @@ def inherit_parents(obj): return result -def get_json_schema_object_fields(obj, enforce_title=False, - mark_required=True): +def get_json_schema_object_fields(obj, enforce_title=False): # Algorithm: # f.e. property => add field info (if field is object then recurse) if obj.get("type") != "object": @@ -175,8 +174,7 @@ def get_json_schema_object_fields(obj, enforce_title=False, try: logger.debug("Processing property %s.%s", obj_title, key_name) required = key_name in required_keys - res = process_prop(key_name, props[key_name], required, - mark_required) + res = process_prop(key_name, props[key_name], required) first_table_rows.append(res["row"]) tables.extend(res["tables"]) @@ -196,7 +194,7 @@ def get_json_schema_object_fields(obj, enforce_title=False, return tables -def process_prop(key_name, prop, required, mark_required): +def process_prop(key_name, prop, required): prop = inherit_parents(prop) value_type = None @@ -213,7 +211,6 @@ def process_prop(key_name, prop, required, mark_required): nested_objects = get_json_schema_object_fields( prop, enforce_title=True, - mark_required=mark_required, ) value_type = nested_objects[0]["title"] value_id = value_type @@ -226,7 +223,6 @@ def process_prop(key_name, prop, required, mark_required): nested_objects = get_json_schema_object_fields( items, enforce_title=True, - mark_required=mark_required, ) value_id = nested_objects[0]["title"] value_type = "[%s]" % value_id @@ -269,7 +265,7 @@ def process_prop(key_name, prop, required, mark_required): value_type = " or ".join(value_type) - if required and mark_required: + if required: desc = "**Required.** " + desc return { @@ -284,10 +280,9 @@ def process_prop(key_name, prop, required, mark_required): } -def get_tables_for_schema(schema, mark_required=True): +def get_tables_for_schema(schema): schema = inherit_parents(schema) - tables = get_json_schema_object_fields(schema, - mark_required=mark_required) + tables = get_json_schema_object_fields(schema) # the result may contain duplicates, if objects are referred to more than # once. Filter them out. @@ -470,9 +465,7 @@ class MatrixUnits(Units): elif res_type and Units.prop(good_response, "schema/properties"): # response is an object: schema = good_response["schema"] - res_tables = get_tables_for_schema(schema, - mark_required=False, - ) + res_tables = get_tables_for_schema(schema) endpoint["res_tables"].extend(res_tables) elif res_type and Units.prop(good_response, "schema/items"): # response is an array: