We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Github Personal Acces Token
### Before submitting your issue:

Enable debug logging in Medusa settings, reproduce the error (be sure to disable after the bug is fixed)
**Python Version**: `2.7.13 (default, Nov 24 2017, 17:33:09) [GCC 6.3.0 20170516]`
**Operating System**: `Linux-3.4.113-bananian-armv7l-with-debian-9.3`
**Locale**: `UTF-8`
**Branch**: [master](../tree/master)
**Database**: `44.9`
**Commit**: pymedusa/Medusa@d6eb72d4e1019e5d1286ae6ac1d7e4b318229ebe
**What you did:** I selected Github personal acces token as authentication method for submitting new issues, entered my token, and tried to submit an issue from within Medusa
**What happened:** It kept giving me the error message that I should enter my username/password
**What you expected:** I expected the issue to be submitted of course but I also expected to still have to enter my username, as is usual AFAIK when logging into Github through a 3rd party service 

Unless I'm gravely mistaken (or made an error while entering my login info, but I triple checked it) I think the way of logging in with a git token is wrong, it's missing the username field, and can thus not work.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `medusa/issue_submitter.py`
Content:
```
1 # coding=utf-8
2 """GitHub issue submitter."""
3 from __future__ import unicode_literals
4 
5 import difflib
6 import locale
7 import logging
8 import platform
9 import sys
10 from builtins import object
11 from builtins import str
12 from datetime import datetime, timedelta
13 
14 from github import InputFileContent
15 from github.GithubException import GithubException, RateLimitExceededException
16 
17 from medusa import app, db
18 from medusa.classes import ErrorViewer
19 from medusa.github_client import authenticate, get_github_repo, token_authenticate
20 from medusa.logger.adapters.style import BraceAdapter
21 
22 log = BraceAdapter(logging.getLogger(__name__))
23 log.logger.addHandler(logging.NullHandler())
24 
25 ISSUE_REPORT = """
26 ### INFO
27 **Python Version**: `{python_version}`
28 **Operating System**: `{os}`
29 **Locale**: `{locale}`
30 **Branch**: [{branch}](../tree/{branch})
31 **Database**: `{db_major_version}.{db_minor_version}`
32 **Commit**: {org}/{repo}@{commit}
33 **Link to Log**: {log_url}
34 ### ERROR
35 {log_line}
36 ---
37 _STAFF NOTIFIED_: @{org}/support @{org}/moderators
38 """
39 
40 
41 class IssueSubmitter(object):
42     """GitHub issue submitter."""
43 
44     MISSING_CREDENTIALS = 'Please set your GitHub Username and Password in the config.  Unable to submit issue ticket to GitHub.'
45     DEBUG_NOT_ENABLED = 'Please enable Debug mode in the config.  Unable to submit issue ticket to GitHub.'
46     NO_ISSUES = 'No issue to be submitted to GitHub.'
47     UNSUPPORTED_VERSION = 'Please update Medusa, unable to submit issue ticket to GitHub with an outdated version.'
48     ALREADY_RUNNING = 'An issue is already being submitted, please wait for it to complete.'
49     BAD_CREDENTIALS = 'Please check your Github credentials in Medusa settings. Bad Credentials error'
50     RATE_LIMIT = 'Please wait before submit new issues. Github Rate Limit Exceeded error'
51     GITHUB_EXCEPTION = 'Error trying to contact Github. Please try again'
52     EXISTING_ISSUE_LOCKED = 'Issue #{number} is locked, check GitHub to find info about the error.'
53     COMMENTED_EXISTING_ISSUE = 'Commented on existing issue #{number} successfully!'
54     ISSUE_CREATED = 'Your issue ticket #{number} was submitted successfully!'
55 
56     TITLE_PREFIX = '[APP SUBMITTED]: '
57 
58     def __init__(self):
59         """Initialize class with the default constructor."""
60         self.running = False
61 
62     @staticmethod
63     def create_gist(github, logline):
64         """Create a private gist with log data for the specified log line."""
65         context_loglines = logline.get_context_loglines()
66         if context_loglines:
67             content = '\n'.join([str(ll) for ll in context_loglines])
68             return github.get_user().create_gist(False, {'application.log': InputFileContent(content)})
69 
70     @staticmethod
71     def create_issue_data(logline, log_url):
72         """Create the issue data expected by github api to be submitted."""
73         try:
74             locale_name = locale.getdefaultlocale()[1]
75         except ValueError:
76             locale_name = 'unknown'
77 
78         # Get current DB version
79         main_db_con = db.DBConnection()
80         cur_branch_major_db_version, cur_branch_minor_db_version = main_db_con.checkDBVersion()
81 
82         commit = app.CUR_COMMIT_HASH
83         base_url = '../blob/{commit}'.format(commit=commit) if commit else None
84         return ISSUE_REPORT.format(
85             python_version=sys.version[:120].replace('\n', ''),
86             os=platform.platform(),
87             locale=locale_name,
88             branch=app.BRANCH,
89             org=app.GIT_ORG,
90             repo=app.GIT_REPO,
91             commit=commit,
92             db_major_version=cur_branch_major_db_version,
93             db_minor_version=cur_branch_minor_db_version,
94             log_url=log_url or '**No Log available**',
95             log_line=logline.format_to_html(base_url=base_url),
96         )
97 
98     @classmethod
99     def find_similar_issues(cls, github_repo, loglines, max_age=timedelta(days=180)):
100         """Find similar issues in the GitHub repository."""
101         results = dict()
102         issues = github_repo.get_issues(state='all', since=datetime.now() - max_age)
103         for issue in issues:
104             if hasattr(issue, 'pull_request') and issue.pull_request:
105                 continue
106             issue_title = issue.title
107             if issue_title.startswith(cls.TITLE_PREFIX):
108                 issue_title = issue_title[len(cls.TITLE_PREFIX):]
109 
110             for logline in loglines:
111                 log_title = logline.issue_title
112                 if cls.similar(log_title, issue_title):
113                     results[logline.key] = issue
114 
115             if len(results) >= len(loglines):
116                 break
117 
118         return results
119 
120     @staticmethod
121     def similar(title1, title2, ratio=0.9):
122         """Compare title similarity."""
123         return difflib.SequenceMatcher(None, title1, title2).ratio() >= ratio
124 
125     def submit_github_issue(self, version_checker, max_issues=500):
126         """Submit errors to github."""
127         def result(message, level=logging.WARNING):
128             log.log(level, message)
129             return [(message, None)]
130 
131         if not app.DEBUG:
132             return result(self.DEBUG_NOT_ENABLED)
133 
134         if not (app.GIT_USERNAME and app.GIT_PASSWORD) or app.GIT_TOKEN:
135             return result(self.MISSING_CREDENTIALS)
136 
137         if not ErrorViewer.errors:
138             return result(self.NO_ISSUES, logging.INFO)
139 
140         if not app.DEVELOPER and version_checker.need_update():
141             return result(self.UNSUPPORTED_VERSION)
142 
143         if self.running:
144             return result(self.ALREADY_RUNNING)
145 
146         self.running = True
147         try:
148             if app.GIT_AUTH_TYPE:
149                 github = token_authenticate(app.GIT_TOKEN)
150             else:
151                 github = authenticate(app.GIT_USERNAME, app.GIT_PASSWORD)
152             if not github:
153                 return result(self.BAD_CREDENTIALS)
154 
155             github_repo = get_github_repo(app.GIT_ORG, app.GIT_REPO, gh=github)
156             loglines = ErrorViewer.errors[:max_issues]
157             similar_issues = self.find_similar_issues(github_repo, loglines)
158 
159             return self.submit_issues(github, github_repo, loglines, similar_issues)
160         except RateLimitExceededException:
161             return result(self.RATE_LIMIT)
162         except (GithubException, IOError):
163             return result(self.GITHUB_EXCEPTION)
164         finally:
165             self.running = False
166 
167     @classmethod
168     def submit_issues(cls, github, github_repo, loglines, similar_issues):
169         """Submit issues to github."""
170         results = []
171         for line in loglines:
172             gist = cls.create_gist(github, line)
173             message = cls.create_issue_data(line, log_url=gist.html_url if gist else None)
174             similar_issue = similar_issues.get(line.key)
175             issue_id = None
176             if similar_issue:
177                 if similar_issue.raw_data['locked']:
178                     submitter_result = cls.EXISTING_ISSUE_LOCKED.format(number=similar_issue.number)
179                     log.warning(submitter_result)
180                 else:
181                     similar_issue.create_comment(message)
182                     issue_id = similar_issue.number
183                     submitter_result = cls.COMMENTED_EXISTING_ISSUE.format(number=issue_id)
184                     log.info(submitter_result)
185                     ErrorViewer.remove(line)
186             else:
187                 issue = github_repo.create_issue('{prefix}{title}'.format(prefix=cls.TITLE_PREFIX, title=line.issue_title), message)
188                 issue_id = issue.number
189                 submitter_result = cls.ISSUE_CREATED.format(number=issue_id)
190                 log.info(submitter_result)
191                 ErrorViewer.remove(line)
192             results.append((submitter_result, issue_id))
193 
194         return results
195
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/medusa/issue_submitter.py b/medusa/issue_submitter.py
--- a/medusa/issue_submitter.py
+++ b/medusa/issue_submitter.py
@@ -12,7 +12,7 @@
 from datetime import datetime, timedelta
 
 from github import InputFileContent
-from github.GithubException import GithubException, RateLimitExceededException
+from github.GithubException import GithubException, RateLimitExceededException, UnknownObjectException
 
 from medusa import app, db
 from medusa.classes import ErrorViewer
@@ -41,14 +41,16 @@
 class IssueSubmitter(object):
     """GitHub issue submitter."""
 
-    MISSING_CREDENTIALS = 'Please set your GitHub Username and Password in the config.  Unable to submit issue ticket to GitHub.'
-    DEBUG_NOT_ENABLED = 'Please enable Debug mode in the config.  Unable to submit issue ticket to GitHub.'
+    MISSING_CREDENTIALS = 'Please set your GitHub Username and Password in the config. Unable to submit issue ticket to GitHub.'
+    MISSING_CREDENTIALS_TOKEN = 'Please set your GitHub personal access token in the config. Unable to submit issue ticket to GitHub.'
+    DEBUG_NOT_ENABLED = 'Please enable Debug mode in the config. Unable to submit issue ticket to GitHub.'
     NO_ISSUES = 'No issue to be submitted to GitHub.'
     UNSUPPORTED_VERSION = 'Please update Medusa, unable to submit issue ticket to GitHub with an outdated version.'
     ALREADY_RUNNING = 'An issue is already being submitted, please wait for it to complete.'
     BAD_CREDENTIALS = 'Please check your Github credentials in Medusa settings. Bad Credentials error'
     RATE_LIMIT = 'Please wait before submit new issues. Github Rate Limit Exceeded error'
     GITHUB_EXCEPTION = 'Error trying to contact Github. Please try again'
+    GITHUB_UNKNOWNOBJECTEXCEPTION = 'GitHub returned an error "Not Found". If using a token, make sure the proper scopes are selected.'
     EXISTING_ISSUE_LOCKED = 'Issue #{number} is locked, check GitHub to find info about the error.'
     COMMENTED_EXISTING_ISSUE = 'Commented on existing issue #{number} successfully!'
     ISSUE_CREATED = 'Your issue ticket #{number} was submitted successfully!'
@@ -131,7 +133,10 @@
         if not app.DEBUG:
             return result(self.DEBUG_NOT_ENABLED)
 
-        if not (app.GIT_USERNAME and app.GIT_PASSWORD) or app.GIT_TOKEN:
+        if app.GIT_AUTH_TYPE == 1 and not app.GIT_TOKEN:
+            return result(self.MISSING_CREDENTIALS_TOKEN)
+
+        if app.GIT_AUTH_TYPE == 0 and not (app.GIT_USERNAME and app.GIT_PASSWORD):
             return result(self.MISSING_CREDENTIALS)
 
         if not ErrorViewer.errors:
@@ -159,7 +164,10 @@
             return self.submit_issues(github, github_repo, loglines, similar_issues)
         except RateLimitExceededException:
             return result(self.RATE_LIMIT)
-        except (GithubException, IOError):
+        except (GithubException, IOError) as error:
+            # If the api return http status 404, authentication or permission issue(token right to create gists)
+            if isinstance(error, UnknownObjectException):
+                return result(self.GITHUB_UNKNOWNOBJECTEXCEPTION)
             return result(self.GITHUB_EXCEPTION)
         finally:
             self.running = False

{"golden_diff": "diff --git a/medusa/issue_submitter.py b/medusa/issue_submitter.py\n--- a/medusa/issue_submitter.py\n+++ b/medusa/issue_submitter.py\n@@ -12,7 +12,7 @@\n from datetime import datetime, timedelta\n \n from github import InputFileContent\n-from github.GithubException import GithubException, RateLimitExceededException\n+from github.GithubException import GithubException, RateLimitExceededException, UnknownObjectException\n \n from medusa import app, db\n from medusa.classes import ErrorViewer\n@@ -41,14 +41,16 @@\n class IssueSubmitter(object):\n     \"\"\"GitHub issue submitter.\"\"\"\n \n-    MISSING_CREDENTIALS = 'Please set your GitHub Username and Password in the config.  Unable to submit issue ticket to GitHub.'\n-    DEBUG_NOT_ENABLED = 'Please enable Debug mode in the config.  Unable to submit issue ticket to GitHub.'\n+    MISSING_CREDENTIALS = 'Please set your GitHub Username and Password in the config. Unable to submit issue ticket to GitHub.'\n+    MISSING_CREDENTIALS_TOKEN = 'Please set your GitHub personal access token in the config. Unable to submit issue ticket to GitHub.'\n+    DEBUG_NOT_ENABLED = 'Please enable Debug mode in the config. Unable to submit issue ticket to GitHub.'\n     NO_ISSUES = 'No issue to be submitted to GitHub.'\n     UNSUPPORTED_VERSION = 'Please update Medusa, unable to submit issue ticket to GitHub with an outdated version.'\n     ALREADY_RUNNING = 'An issue is already being submitted, please wait for it to complete.'\n     BAD_CREDENTIALS = 'Please check your Github credentials in Medusa settings. Bad Credentials error'\n     RATE_LIMIT = 'Please wait before submit new issues. Github Rate Limit Exceeded error'\n     GITHUB_EXCEPTION = 'Error trying to contact Github. Please try again'\n+    GITHUB_UNKNOWNOBJECTEXCEPTION = 'GitHub returned an error \"Not Found\". If using a token, make sure the proper scopes are selected.'\n     EXISTING_ISSUE_LOCKED = 'Issue #{number} is locked, check GitHub to find info about the error.'\n     COMMENTED_EXISTING_ISSUE = 'Commented on existing issue #{number} successfully!'\n     ISSUE_CREATED = 'Your issue ticket #{number} was submitted successfully!'\n@@ -131,7 +133,10 @@\n         if not app.DEBUG:\n             return result(self.DEBUG_NOT_ENABLED)\n \n-        if not (app.GIT_USERNAME and app.GIT_PASSWORD) or app.GIT_TOKEN:\n+        if app.GIT_AUTH_TYPE == 1 and not app.GIT_TOKEN:\n+            return result(self.MISSING_CREDENTIALS_TOKEN)\n+\n+        if app.GIT_AUTH_TYPE == 0 and not (app.GIT_USERNAME and app.GIT_PASSWORD):\n             return result(self.MISSING_CREDENTIALS)\n \n         if not ErrorViewer.errors:\n@@ -159,7 +164,10 @@\n             return self.submit_issues(github, github_repo, loglines, similar_issues)\n         except RateLimitExceededException:\n             return result(self.RATE_LIMIT)\n-        except (GithubException, IOError):\n+        except (GithubException, IOError) as error:\n+            # If the api return http status 404, authentication or permission issue(token right to create gists)\n+            if isinstance(error, UnknownObjectException):\n+                return result(self.GITHUB_UNKNOWNOBJECTEXCEPTION)\n             return result(self.GITHUB_EXCEPTION)\n         finally:\n             self.running = False\n", "issue": "Github Personal Acces Token\n### Before submitting your issue:\r\n\r\nEnable debug logging in Medusa settings, reproduce the error (be sure to disable after the bug is fixed)\r\n**Python Version**: `2.7.13 (default, Nov 24 2017, 17:33:09) [GCC 6.3.0 20170516]`\r\n**Operating System**: `Linux-3.4.113-bananian-armv7l-with-debian-9.3`\r\n**Locale**: `UTF-8`\r\n**Branch**: [master](../tree/master)\r\n**Database**: `44.9`\r\n**Commit**: pymedusa/Medusa@d6eb72d4e1019e5d1286ae6ac1d7e4b318229ebe\r\n**What you did:** I selected Github personal acces token as authentication method for submitting new issues, entered my token, and tried to submit an issue from within Medusa\r\n**What happened:** It kept giving me the error message that I should enter my username/password\r\n**What you expected:** I expected the issue to be submitted of course but I also expected to still have to enter my username, as is usual AFAIK when logging into Github through a 3rd party service \r\n\r\nUnless I'm gravely mistaken (or made an error while entering my login info, but I triple checked it) I think the way of logging in with a git token is wrong, it's missing the username field, and can thus not work.\n", "before_files": [{"content": "# coding=utf-8\n\"\"\"GitHub issue submitter.\"\"\"\nfrom __future__ import unicode_literals\n\nimport difflib\nimport locale\nimport logging\nimport platform\nimport sys\nfrom builtins import object\nfrom builtins import str\nfrom datetime import datetime, timedelta\n\nfrom github import InputFileContent\nfrom github.GithubException import GithubException, RateLimitExceededException\n\nfrom medusa import app, db\nfrom medusa.classes import ErrorViewer\nfrom medusa.github_client import authenticate, get_github_repo, token_authenticate\nfrom medusa.logger.adapters.style import BraceAdapter\n\nlog = BraceAdapter(logging.getLogger(__name__))\nlog.logger.addHandler(logging.NullHandler())\n\nISSUE_REPORT = \"\"\"\n### INFO\n**Python Version**: `{python_version}`\n**Operating System**: `{os}`\n**Locale**: `{locale}`\n**Branch**: [{branch}](../tree/{branch})\n**Database**: `{db_major_version}.{db_minor_version}`\n**Commit**: {org}/{repo}@{commit}\n**Link to Log**: {log_url}\n### ERROR\n{log_line}\n---\n_STAFF NOTIFIED_: @{org}/support @{org}/moderators\n\"\"\"\n\n\nclass IssueSubmitter(object):\n    \"\"\"GitHub issue submitter.\"\"\"\n\n    MISSING_CREDENTIALS = 'Please set your GitHub Username and Password in the config.  Unable to submit issue ticket to GitHub.'\n    DEBUG_NOT_ENABLED = 'Please enable Debug mode in the config.  Unable to submit issue ticket to GitHub.'\n    NO_ISSUES = 'No issue to be submitted to GitHub.'\n    UNSUPPORTED_VERSION = 'Please update Medusa, unable to submit issue ticket to GitHub with an outdated version.'\n    ALREADY_RUNNING = 'An issue is already being submitted, please wait for it to complete.'\n    BAD_CREDENTIALS = 'Please check your Github credentials in Medusa settings. Bad Credentials error'\n    RATE_LIMIT = 'Please wait before submit new issues. Github Rate Limit Exceeded error'\n    GITHUB_EXCEPTION = 'Error trying to contact Github. Please try again'\n    EXISTING_ISSUE_LOCKED = 'Issue #{number} is locked, check GitHub to find info about the error.'\n    COMMENTED_EXISTING_ISSUE = 'Commented on existing issue #{number} successfully!'\n    ISSUE_CREATED = 'Your issue ticket #{number} was submitted successfully!'\n\n    TITLE_PREFIX = '[APP SUBMITTED]: '\n\n    def __init__(self):\n        \"\"\"Initialize class with the default constructor.\"\"\"\n        self.running = False\n\n    @staticmethod\n    def create_gist(github, logline):\n        \"\"\"Create a private gist with log data for the specified log line.\"\"\"\n        context_loglines = logline.get_context_loglines()\n        if context_loglines:\n            content = '\\n'.join([str(ll) for ll in context_loglines])\n            return github.get_user().create_gist(False, {'application.log': InputFileContent(content)})\n\n    @staticmethod\n    def create_issue_data(logline, log_url):\n        \"\"\"Create the issue data expected by github api to be submitted.\"\"\"\n        try:\n            locale_name = locale.getdefaultlocale()[1]\n        except ValueError:\n            locale_name = 'unknown'\n\n        # Get current DB version\n        main_db_con = db.DBConnection()\n        cur_branch_major_db_version, cur_branch_minor_db_version = main_db_con.checkDBVersion()\n\n        commit = app.CUR_COMMIT_HASH\n        base_url = '../blob/{commit}'.format(commit=commit) if commit else None\n        return ISSUE_REPORT.format(\n            python_version=sys.version[:120].replace('\\n', ''),\n            os=platform.platform(),\n            locale=locale_name,\n            branch=app.BRANCH,\n            org=app.GIT_ORG,\n            repo=app.GIT_REPO,\n            commit=commit,\n            db_major_version=cur_branch_major_db_version,\n            db_minor_version=cur_branch_minor_db_version,\n            log_url=log_url or '**No Log available**',\n            log_line=logline.format_to_html(base_url=base_url),\n        )\n\n    @classmethod\n    def find_similar_issues(cls, github_repo, loglines, max_age=timedelta(days=180)):\n        \"\"\"Find similar issues in the GitHub repository.\"\"\"\n        results = dict()\n        issues = github_repo.get_issues(state='all', since=datetime.now() - max_age)\n        for issue in issues:\n            if hasattr(issue, 'pull_request') and issue.pull_request:\n                continue\n            issue_title = issue.title\n            if issue_title.startswith(cls.TITLE_PREFIX):\n                issue_title = issue_title[len(cls.TITLE_PREFIX):]\n\n            for logline in loglines:\n                log_title = logline.issue_title\n                if cls.similar(log_title, issue_title):\n                    results[logline.key] = issue\n\n            if len(results) >= len(loglines):\n                break\n\n        return results\n\n    @staticmethod\n    def similar(title1, title2, ratio=0.9):\n        \"\"\"Compare title similarity.\"\"\"\n        return difflib.SequenceMatcher(None, title1, title2).ratio() >= ratio\n\n    def submit_github_issue(self, version_checker, max_issues=500):\n        \"\"\"Submit errors to github.\"\"\"\n        def result(message, level=logging.WARNING):\n            log.log(level, message)\n            return [(message, None)]\n\n        if not app.DEBUG:\n            return result(self.DEBUG_NOT_ENABLED)\n\n        if not (app.GIT_USERNAME and app.GIT_PASSWORD) or app.GIT_TOKEN:\n            return result(self.MISSING_CREDENTIALS)\n\n        if not ErrorViewer.errors:\n            return result(self.NO_ISSUES, logging.INFO)\n\n        if not app.DEVELOPER and version_checker.need_update():\n            return result(self.UNSUPPORTED_VERSION)\n\n        if self.running:\n            return result(self.ALREADY_RUNNING)\n\n        self.running = True\n        try:\n            if app.GIT_AUTH_TYPE:\n                github = token_authenticate(app.GIT_TOKEN)\n            else:\n                github = authenticate(app.GIT_USERNAME, app.GIT_PASSWORD)\n            if not github:\n                return result(self.BAD_CREDENTIALS)\n\n            github_repo = get_github_repo(app.GIT_ORG, app.GIT_REPO, gh=github)\n            loglines = ErrorViewer.errors[:max_issues]\n            similar_issues = self.find_similar_issues(github_repo, loglines)\n\n            return self.submit_issues(github, github_repo, loglines, similar_issues)\n        except RateLimitExceededException:\n            return result(self.RATE_LIMIT)\n        except (GithubException, IOError):\n            return result(self.GITHUB_EXCEPTION)\n        finally:\n            self.running = False\n\n    @classmethod\n    def submit_issues(cls, github, github_repo, loglines, similar_issues):\n        \"\"\"Submit issues to github.\"\"\"\n        results = []\n        for line in loglines:\n            gist = cls.create_gist(github, line)\n            message = cls.create_issue_data(line, log_url=gist.html_url if gist else None)\n            similar_issue = similar_issues.get(line.key)\n            issue_id = None\n            if similar_issue:\n                if similar_issue.raw_data['locked']:\n                    submitter_result = cls.EXISTING_ISSUE_LOCKED.format(number=similar_issue.number)\n                    log.warning(submitter_result)\n                else:\n                    similar_issue.create_comment(message)\n                    issue_id = similar_issue.number\n                    submitter_result = cls.COMMENTED_EXISTING_ISSUE.format(number=issue_id)\n                    log.info(submitter_result)\n                    ErrorViewer.remove(line)\n            else:\n                issue = github_repo.create_issue('{prefix}{title}'.format(prefix=cls.TITLE_PREFIX, title=line.issue_title), message)\n                issue_id = issue.number\n                submitter_result = cls.ISSUE_CREATED.format(number=issue_id)\n                log.info(submitter_result)\n                ErrorViewer.remove(line)\n            results.append((submitter_result, issue_id))\n\n        return results\n", "path": "medusa/issue_submitter.py"}], "after_files": [{"content": "# coding=utf-8\n\"\"\"GitHub issue submitter.\"\"\"\nfrom __future__ import unicode_literals\n\nimport difflib\nimport locale\nimport logging\nimport platform\nimport sys\nfrom builtins import object\nfrom builtins import str\nfrom datetime import datetime, timedelta\n\nfrom github import InputFileContent\nfrom github.GithubException import GithubException, RateLimitExceededException, UnknownObjectException\n\nfrom medusa import app, db\nfrom medusa.classes import ErrorViewer\nfrom medusa.github_client import authenticate, get_github_repo, token_authenticate\nfrom medusa.logger.adapters.style import BraceAdapter\n\nlog = BraceAdapter(logging.getLogger(__name__))\nlog.logger.addHandler(logging.NullHandler())\n\nISSUE_REPORT = \"\"\"\n### INFO\n**Python Version**: `{python_version}`\n**Operating System**: `{os}`\n**Locale**: `{locale}`\n**Branch**: [{branch}](../tree/{branch})\n**Database**: `{db_major_version}.{db_minor_version}`\n**Commit**: {org}/{repo}@{commit}\n**Link to Log**: {log_url}\n### ERROR\n{log_line}\n---\n_STAFF NOTIFIED_: @{org}/support @{org}/moderators\n\"\"\"\n\n\nclass IssueSubmitter(object):\n    \"\"\"GitHub issue submitter.\"\"\"\n\n    MISSING_CREDENTIALS = 'Please set your GitHub Username and Password in the config. Unable to submit issue ticket to GitHub.'\n    MISSING_CREDENTIALS_TOKEN = 'Please set your GitHub personal access token in the config. Unable to submit issue ticket to GitHub.'\n    DEBUG_NOT_ENABLED = 'Please enable Debug mode in the config. Unable to submit issue ticket to GitHub.'\n    NO_ISSUES = 'No issue to be submitted to GitHub.'\n    UNSUPPORTED_VERSION = 'Please update Medusa, unable to submit issue ticket to GitHub with an outdated version.'\n    ALREADY_RUNNING = 'An issue is already being submitted, please wait for it to complete.'\n    BAD_CREDENTIALS = 'Please check your Github credentials in Medusa settings. Bad Credentials error'\n    RATE_LIMIT = 'Please wait before submit new issues. Github Rate Limit Exceeded error'\n    GITHUB_EXCEPTION = 'Error trying to contact Github. Please try again'\n    GITHUB_UNKNOWNOBJECTEXCEPTION = 'GitHub returned an error \"Not Found\". If using a token, make sure the proper scopes are selected.'\n    EXISTING_ISSUE_LOCKED = 'Issue #{number} is locked, check GitHub to find info about the error.'\n    COMMENTED_EXISTING_ISSUE = 'Commented on existing issue #{number} successfully!'\n    ISSUE_CREATED = 'Your issue ticket #{number} was submitted successfully!'\n\n    TITLE_PREFIX = '[APP SUBMITTED]: '\n\n    def __init__(self):\n        \"\"\"Initialize class with the default constructor.\"\"\"\n        self.running = False\n\n    @staticmethod\n    def create_gist(github, logline):\n        \"\"\"Create a private gist with log data for the specified log line.\"\"\"\n        context_loglines = logline.get_context_loglines()\n        if context_loglines:\n            content = '\\n'.join([str(ll) for ll in context_loglines])\n            return github.get_user().create_gist(False, {'application.log': InputFileContent(content)})\n\n    @staticmethod\n    def create_issue_data(logline, log_url):\n        \"\"\"Create the issue data expected by github api to be submitted.\"\"\"\n        try:\n            locale_name = locale.getdefaultlocale()[1]\n        except ValueError:\n            locale_name = 'unknown'\n\n        # Get current DB version\n        main_db_con = db.DBConnection()\n        cur_branch_major_db_version, cur_branch_minor_db_version = main_db_con.checkDBVersion()\n\n        commit = app.CUR_COMMIT_HASH\n        base_url = '../blob/{commit}'.format(commit=commit) if commit else None\n        return ISSUE_REPORT.format(\n            python_version=sys.version[:120].replace('\\n', ''),\n            os=platform.platform(),\n            locale=locale_name,\n            branch=app.BRANCH,\n            org=app.GIT_ORG,\n            repo=app.GIT_REPO,\n            commit=commit,\n            db_major_version=cur_branch_major_db_version,\n            db_minor_version=cur_branch_minor_db_version,\n            log_url=log_url or '**No Log available**',\n            log_line=logline.format_to_html(base_url=base_url),\n        )\n\n    @classmethod\n    def find_similar_issues(cls, github_repo, loglines, max_age=timedelta(days=180)):\n        \"\"\"Find similar issues in the GitHub repository.\"\"\"\n        results = dict()\n        issues = github_repo.get_issues(state='all', since=datetime.now() - max_age)\n        for issue in issues:\n            if hasattr(issue, 'pull_request') and issue.pull_request:\n                continue\n            issue_title = issue.title\n            if issue_title.startswith(cls.TITLE_PREFIX):\n                issue_title = issue_title[len(cls.TITLE_PREFIX):]\n\n            for logline in loglines:\n                log_title = logline.issue_title\n                if cls.similar(log_title, issue_title):\n                    results[logline.key] = issue\n\n            if len(results) >= len(loglines):\n                break\n\n        return results\n\n    @staticmethod\n    def similar(title1, title2, ratio=0.9):\n        \"\"\"Compare title similarity.\"\"\"\n        return difflib.SequenceMatcher(None, title1, title2).ratio() >= ratio\n\n    def submit_github_issue(self, version_checker, max_issues=500):\n        \"\"\"Submit errors to github.\"\"\"\n        def result(message, level=logging.WARNING):\n            log.log(level, message)\n            return [(message, None)]\n\n        if not app.DEBUG:\n            return result(self.DEBUG_NOT_ENABLED)\n\n        if app.GIT_AUTH_TYPE == 1 and not app.GIT_TOKEN:\n            return result(self.MISSING_CREDENTIALS_TOKEN)\n\n        if app.GIT_AUTH_TYPE == 0 and not (app.GIT_USERNAME and app.GIT_PASSWORD):\n            return result(self.MISSING_CREDENTIALS)\n\n        if not ErrorViewer.errors:\n            return result(self.NO_ISSUES, logging.INFO)\n\n        if not app.DEVELOPER and version_checker.need_update():\n            return result(self.UNSUPPORTED_VERSION)\n\n        if self.running:\n            return result(self.ALREADY_RUNNING)\n\n        self.running = True\n        try:\n            if app.GIT_AUTH_TYPE:\n                github = token_authenticate(app.GIT_TOKEN)\n            else:\n                github = authenticate(app.GIT_USERNAME, app.GIT_PASSWORD)\n            if not github:\n                return result(self.BAD_CREDENTIALS)\n\n            github_repo = get_github_repo(app.GIT_ORG, app.GIT_REPO, gh=github)\n            loglines = ErrorViewer.errors[:max_issues]\n            similar_issues = self.find_similar_issues(github_repo, loglines)\n\n            return self.submit_issues(github, github_repo, loglines, similar_issues)\n        except RateLimitExceededException:\n            return result(self.RATE_LIMIT)\n        except (GithubException, IOError) as error:\n            # If the api return http status 404, authentication or permission issue(token right to create gists)\n            if isinstance(error, UnknownObjectException):\n                return result(self.GITHUB_UNKNOWNOBJECTEXCEPTION)\n            return result(self.GITHUB_EXCEPTION)\n        finally:\n            self.running = False\n\n    @classmethod\n    def submit_issues(cls, github, github_repo, loglines, similar_issues):\n        \"\"\"Submit issues to github.\"\"\"\n        results = []\n        for line in loglines:\n            gist = cls.create_gist(github, line)\n            message = cls.create_issue_data(line, log_url=gist.html_url if gist else None)\n            similar_issue = similar_issues.get(line.key)\n            issue_id = None\n            if similar_issue:\n                if similar_issue.raw_data['locked']:\n                    submitter_result = cls.EXISTING_ISSUE_LOCKED.format(number=similar_issue.number)\n                    log.warning(submitter_result)\n                else:\n                    similar_issue.create_comment(message)\n                    issue_id = similar_issue.number\n                    submitter_result = cls.COMMENTED_EXISTING_ISSUE.format(number=issue_id)\n                    log.info(submitter_result)\n                    ErrorViewer.remove(line)\n            else:\n                issue = github_repo.create_issue('{prefix}{title}'.format(prefix=cls.TITLE_PREFIX, title=line.issue_title), message)\n                issue_id = issue.number\n                submitter_result = cls.ISSUE_CREATED.format(number=issue_id)\n                log.info(submitter_result)\n                ErrorViewer.remove(line)\n            results.append((submitter_result, issue_id))\n\n        return results\n", "path": "medusa/issue_submitter.py"}]}